home *** CD-ROM | disk | FTP | other *** search
/ Usenet 1993 July / InfoMagic USENET CD-ROM July 1993.ISO / sources / unix / volume25 / msgd < prev    next >
Encoding:
Text File  |  1992-03-10  |  68.6 KB  |  2,610 lines

  1. Newsgroups: comp.sources.unix
  2. From: jmsellens@watdragon.waterloo.edu (John M. Sellens)
  3. Subject: v25i151: msgd - sends a one line message to another user or users
  4. Sender: unix-sources-moderator@pa.dec.com
  5. Approved: vixie@pa.dec.com
  6.  
  7. Submitted-By: jmsellens@watdragon.waterloo.edu (John M. Sellens)
  8. Posting-Number: Volume 25, Issue 151
  9. Archive-Name: msgd
  10.  
  11. [ name changed from msg to msgd to prevent name collision from volume 4.
  12.   i'm rethinking the archive index to see whether such collisions are
  13.   neccessary.                        --vix ]
  14.  
  15. MSG sends a one line message to another user or users, possibly over
  16. the network.  We like it much more than write(1) and talk(1).
  17.  
  18.     jmsellens@watdragon.waterloo.edu (John M. Sellens)
  19.  
  20. #! /bin/sh
  21. # This is a shell archive.  Remove anything before this line, then unpack
  22. # it by saving it into a file and typing "sh file".  To overwrite existing
  23. # files, type "sh file -c".  You can also feed this as standard input via
  24. # unshar, or by typing "sh <file", e.g..  If this archive is complete, you
  25. # will see the following message at the end:
  26. #        "End of shell archive."
  27. # Contents:  ./README ./Common ./Common/answerback.c ./Common/deliver.c
  28. #   ./Common/errtext.c ./Common/misc.c ./Common/savemsg.c ./Include
  29. #   ./Include/msg.h ./Include/msgoptions.h ./Makefile ./Man
  30. #   ./Man/Makefile ./Man/mesg.1 ./Man/msg.1 ./Man/msgd.8 ./inetd.conf
  31. #   ./mesg ./mesg/Makefile ./mesg/mesg.c ./msg ./msg/Makefile
  32. #   ./msg/msg.c ./msg/remote.c ./msgd ./msgd/Makefile ./msgd/msgd.c
  33. #   ./msgd/server.c ./services
  34. # Wrapped by jmsellen@watmath on Mon Mar  2 01:54:49 1992
  35. PATH=/bin:/usr/bin:/usr/ucb ; export PATH
  36. if test -f './README' -a "${1}" != "-c" ; then 
  37.   echo shar: Will not clobber existing file \"'./README'\"
  38. else
  39. echo shar: Extracting \"'./README'\" \(1625 characters\)
  40. sed "s/^X//" >'./README' <<'END_OF_FILE'
  41. XMSG sends a one line message to another user or users, possibly over
  42. Xthe network.  We like it much more than write(1) and talk(1).
  43. X
  44. XFor example,
  45. X  % msg jdoe@othermachine
  46. X  Let's go eat!
  47. X  %
  48. X  jdoe@othermachine: ok - where?
  49. X  msg -r
  50. X  msg: Replying to 'jdoe@othermachine'
  51. X  How about the cafeteria?
  52. X  %
  53. X
  54. XTo install, add the lines to /etc/services and /etc/inetd.conf,
  55. Xmodify the Makefile and */Makefile to your needs, and adjust
  56. XInclude/msgoptions.h to set the options that are appropriate for you.
  57. X
  58. Xmesg is a modified version of the Berkeley mesg program.  The Tahoe
  59. Xversion appears with the Berkeley copyright - this version is based on
  60. X4.2 or 4.3, and so I added the Berkeley copyright notice, and assume
  61. Xthat distribution is ok.  This version allows you to set an answerback
  62. Xmessage that will be given to any user trying to send you a message.
  63. XNote that this version has to be setuid root so that it can remove
  64. Xother users answerback message files.
  65. X
  66. XWe use this on Sun3, Sun4, BSD Vax, Ultrix Vax, MIPS, DEC MIPS, and Sequent.
  67. X
  68. XNote that the service number that we use has not been officially
  69. Xregistered.  If I ever get off my butt, and register a real number,
  70. Xit should be relatively easy to update things.  Or so I like to think.
  71. XI'd like to encourage everyone to use the same port number i.e. 1241/tcp,
  72. Xotherwise we won't be able to talk to each other.
  73. X
  74. XNaturally, no warranties, bug fixes and enhancements accepted, but
  75. Xno support committments.  Available via anonymous ftp from
  76. Xwatmath.waterloo.edu in pub/msg.shar.
  77. X
  78. XJohn Sellens
  79. XMath Faculty Computing Facility
  80. XUniversity of Waterloo
  81. Xjmsellens@watmath.waterloo.edu
  82. END_OF_FILE
  83. if test 1625 -ne `wc -c <'./README'`; then
  84.     echo shar: \"'./README'\" unpacked with wrong size!
  85. fi
  86. # end of './README'
  87. fi
  88. if test ! -d './Common' ; then
  89.     echo shar: Creating directory \"'./Common'\"
  90.     mkdir './Common'
  91. fi
  92. if test -f './Common/answerback.c' -a "${1}" != "-c" ; then 
  93.   echo shar: Will not clobber existing file \"'./Common/answerback.c'\"
  94. else
  95. echo shar: Extracting \"'./Common/answerback.c'\" \(2095 characters\)
  96. sed "s/^X//" >'./Common/answerback.c' <<'END_OF_FILE'
  97. X#ifndef lint
  98. Xstatic char *RCSid = "$Header: /fsys4/usr/source/users/msg/Common/RCS/answerback.c,v 1.2 90/12/29 21:59:53 jmsellen Exp $";
  99. X#endif
  100. X
  101. X#if 0
  102. X/*
  103. X * $Log:    answerback.c,v $
  104. X * Revision 1.2  90/12/29  21:59:53  jmsellen
  105. X * Use ANSBACK define from Include/msg.h
  106. X * 
  107. X * Revision 1.1  87/08/06  19:06:19  sahayman
  108. X * Initial revision
  109. X * 
  110. X */
  111. X#endif
  112. X
  113. X/* answerback.c
  114. X   Return a user's answerback message to the person who sent him a
  115. X   message.
  116. X*/
  117. X
  118. X#include "msg.h"
  119. X#include <pwd.h>
  120. X
  121. X#define MYBUFSIZ    (BUFSIZ/2)    /* BUFSIZ is max errmsg size */
  122. X
  123. X
  124. X/* We may be sending to multiple instances of the same user, so it makes
  125. X   since to remember the last user we looked up and his/her UID to avoid
  126. X   searching the passwd file again. */
  127. X
  128. Xanswerback( errcode, user, line )
  129. Xint errcode;
  130. Xchar *user;
  131. Xchar *line;
  132. X{
  133. X    static char lastuser[25];    /* too hard to use sizeof() */
  134. X    static int lastuid = -1;
  135. X    struct stat sbuf;
  136. X    FILE *fp;
  137. X    char answerbuf[sizeof(ANSBACK)+25];  /* lots of extra room */
  138. X    /* find name of answerback file */
  139. X    (void) sprintf( answerbuf, "%s%s", ANSBACK, line );
  140. X    /* Now make sure that if the answerback file exists, it belongs to
  141. X       the user we're sending to */
  142. X    if ( stat( answerbuf, &sbuf ) == -1 )
  143. X    return;        /* no answerback exists */
  144. X    if ( strcmp( user, lastuser ) != 0 ) {
  145. X    /* we don't know this guy, so look him up */
  146. X    struct passwd *pw = getpwnam( user );
  147. X    endpwent();
  148. X    if ( pw == (struct passwd *)NULL )
  149. X        /* I know this guy exists, but ignore it */
  150. X        return;
  151. X    (void) strcpy( lastuser, user );
  152. X    lastuid = pw->pw_uid;
  153. X    }
  154. X    if ( sbuf.st_uid != lastuid )
  155. X    return;        /* not his file */
  156. X    /* we don't care if we can't read his message - it's his problem */
  157. X    if ( (fp=fopen(answerbuf,"r")) != FPNULL ) {
  158. X    char buf[MYBUFSIZ+1];
  159. X    int len;
  160. X    if ( (len=fread( buf, 1, MYBUFSIZ, fp )) > 0 ) {
  161. X        if ( buf[len-1] =='\n' ) len--;
  162. X        buf[len] = '\0'; /* make it terminated */
  163. X        if ( errcode == ANS_WARN )
  164. X        errmsg( errcode, user, line, buf );
  165. X        else
  166. X        errmsg( errcode, user, hostname, line, buf );
  167. X    }
  168. X    (void) fclose( fp );
  169. X    }
  170. X}
  171. END_OF_FILE
  172. if test 2095 -ne `wc -c <'./Common/answerback.c'`; then
  173.     echo shar: \"'./Common/answerback.c'\" unpacked with wrong size!
  174. fi
  175. # end of './Common/answerback.c'
  176. fi
  177. if test -f './Common/deliver.c' -a "${1}" != "-c" ; then 
  178.   echo shar: Will not clobber existing file \"'./Common/deliver.c'\"
  179. else
  180. echo shar: Extracting \"'./Common/deliver.c'\" \(4264 characters\)
  181. sed "s/^X//" >'./Common/deliver.c' <<'END_OF_FILE'
  182. X#ifndef lint
  183. Xstatic char *RCSid = "$Header: /fsys4/usr/source/users/msg/Common/RCS/deliver.c,v 1.4 90/12/29 21:59:07 jmsellen Exp $";
  184. X#endif
  185. X
  186. X/* deliver.c
  187. X   Deliver a message to a user on this machine.
  188. X*/
  189. X
  190. X/*
  191. X * Old revision log:
  192. X *
  193. X * Revision 1.4  87/06/04  12:49:47  jmsellens
  194. X * Changes to put the msg save file in /usr/tmp
  195. X * rationalized the code a little, added the NO_STAT error condition
  196. X * 
  197. X * Revision 1.3  87/04/13  09:46:09  sahayman
  198. X * Make sure to do answerback() on unsuccessful messages (mesg n)
  199. X * as well as successful.
  200. X * 
  201. X * Revision 1.2  87/04/06  02:16:30  sahayman
  202. X * Print a "However ... " message when unable to deliver to some
  203. X * ttys but able to deliver to others.
  204. X * 
  205. X */
  206. X#include "msg.h"
  207. X#include <setjmp.h>
  208. X#include <signal.h>
  209. X#include <ctype.h>
  210. X
  211. Xstatic jmp_buf timeout;
  212. X
  213. X
  214. Xstatic
  215. Xwakeup()
  216. X{
  217. X    longjmp( timeout, 1 );
  218. X}
  219. X
  220. X
  221. X
  222. Xint
  223. Xdeliver( sender, user, message, fromroot )
  224. Xchar *sender, *user, *message;
  225. X{
  226. X    struct utmp ut;
  227. X    FILE *fp, *term;
  228. X    char terminal[40];    /* should be enough ... */
  229. X    int found = 0, errcode = 0;
  230. X    int however = 0;    /* Should we print a "however ...." msg */
  231. X    struct stat sbuf;
  232. X    char line[sizeof(ut.ut_line)+5];
  233. X    char successful_line[sizeof(ut.ut_line)+5];
  234. X    int (*osig)();
  235. X#ifdef SAVEMSG
  236. X    int uid = -1;
  237. X#endif
  238. X
  239. X    successful_line[0] = '\0';
  240. X
  241. X    if ( (fp=fopen( UTMP, "r" )) == FPNULL ) {
  242. X    errmsg( NO_UTMP, hostname, syserr() );
  243. X    return( NO_UTMP );
  244. X    }
  245. X    /* keep on until end of file in case s/he's signed on more than once */
  246. X    while ( fread( &ut, sizeof(struct utmp), 1, fp ) == 1 ) {
  247. X    if ( strncmp( user, ut.ut_name, sizeof(ut.ut_name) ) != 0 )
  248. X        continue;
  249. X#ifdef SYSV_UTMP
  250. X    if ( ut.ut_type != USER_PROCESS )
  251. X        continue;
  252. X#endif
  253. X    found++;
  254. X    (void) strncpy( line, ut.ut_line, sizeof(ut.ut_line) );
  255. X    line[sizeof(ut.ut_line)] = '\0';
  256. X    (void) sprintf( terminal, "%s%s", DEV, line );
  257. X    /* stat it to see if we're allowed to write */
  258. X    if ( stat(terminal,&sbuf) == 0 ) {
  259. X#ifdef SAVEMSG
  260. X        uid = sbuf.st_uid;
  261. X#endif
  262. X        if ( ((sbuf.st_mode&ALLOW)==0) && !fromroot ) {
  263. X        errmsg( MESG_OFF, user, hostname, line );
  264. X        however++;
  265. X        errcode++;
  266. X        } else {
  267. X        if ( setjmp( timeout ) ) {
  268. X            errmsg( TIMEOUT, user, hostname, line );
  269. X            however++;
  270. X        } else {
  271. X            osig = signal(SIGALRM, wakeup);
  272. X            alarm( 5 );
  273. X            if ( (term=fopen(terminal,"w")) != NULL ) {
  274. X            fprintf(term, "\n\007%s: %s\n", sender, message);
  275. X            /* we need this fflush() or else it would hang in the
  276. X               fclose() after we've dealt with the alarm() */
  277. X            fflush( term );
  278. X            strcpy( successful_line, line );
  279. X            }
  280. X        }
  281. X        alarm( 0 );
  282. X        signal(SIGALRM, osig);
  283. X        if (term == NULL) {
  284. X            errmsg( NO_WRITE, user, hostname, line, syserr() );
  285. X            however++;
  286. X            errcode++;
  287. X        } else
  288. X            fclose( term );
  289. X        }
  290. X#ifdef ANSWERBACK
  291. X        answerback( ANSWER, user, line );
  292. X#endif
  293. X    } else {
  294. X        errmsg( NO_STAT, terminal, user, hostname, syserr() );
  295. X        however++;
  296. X        errcode++;
  297. X    }
  298. X    }
  299. X    (void) fclose( fp );
  300. X#ifdef SAVEMSG
  301. X    /* note that these saves it even if mesg n was set */
  302. X    if ( found && uid != -1 )
  303. X    savemsg( uid, user, sender, message );
  304. X#endif
  305. X    if ( !found ) {
  306. X    errmsg( NOT_ON, user, hostname );
  307. X    errcode++;
  308. X    }
  309. X    /*
  310. X     * A message like "so-and-so (ttyxx) is not receiving messages"
  311. X     * is not too helpful when they are receiving messages
  312. X     * on another terminal.  So mention that.
  313. X     * ..sah 87/04/06
  314. X     */
  315. X
  316. X    if ( however && successful_line[0] ) {
  317. X    errmsg( HOWEVER, user, hostname, successful_line );
  318. X    }
  319. X    return( errcode );
  320. X}
  321. X
  322. X
  323. X#define DEL    (127)
  324. X
  325. Xsanitize( mbuf, copy )
  326. Xchar *mbuf;
  327. Xchar *copy;
  328. X{
  329. X    char *p, *r;
  330. X    /*
  331. X     * Remove control characters to prevent nasties.
  332. X     * Previously allowed isspace(*p), but having a \r in a message
  333. X     * is asking for forgeries.  isprint() is sufficient.
  334. X     * (And good programmers always use isascii() first, right?)
  335. X     */
  336. X    for ( p = mbuf, r = copy; *p; p++,r++ ) {
  337. X    if ( ! isascii( *p ) ) {
  338. X        *r++ = '\\';
  339. X        *p = toascii( *p );
  340. X    }
  341. X    if ( ! isprint(*p) ) {
  342. X        if ( *p == '\t' )
  343. X        *r = ' ';
  344. X        else if ( iscntrl( *p ) ) {
  345. X        *r++ = '^';
  346. X        if ( *p == DEL )
  347. X            *r = '?';
  348. X        else
  349. X            *r = *p + '@';
  350. X        } else    /* this shouldn't happen, but what the hell */
  351. X        *r = 'X';
  352. X    } else
  353. X        *r = *p;
  354. X    }
  355. X}
  356. END_OF_FILE
  357. if test 4264 -ne `wc -c <'./Common/deliver.c'`; then
  358.     echo shar: \"'./Common/deliver.c'\" unpacked with wrong size!
  359. fi
  360. # end of './Common/deliver.c'
  361. fi
  362. if test -f './Common/errtext.c' -a "${1}" != "-c" ; then 
  363.   echo shar: Will not clobber existing file \"'./Common/errtext.c'\"
  364. else
  365. echo shar: Extracting \"'./Common/errtext.c'\" \(2177 characters\)
  366. sed "s/^X//" >'./Common/errtext.c' <<'END_OF_FILE'
  367. X#ifndef lint
  368. Xstatic char *RCSid = "$Header: /usr/source/mfcf/msg/common/RCS/errtext.c,v 1.3 89/01/08 03:16:36 jmsellens Exp $";
  369. X#endif
  370. X
  371. X#if 0
  372. X/*
  373. X * $Log:    errtext.c,v $
  374. X * Revision 1.3  89/01/08  03:16:36  jmsellens
  375. X * Changed BADHOST error message to not mention hosts file, since
  376. X * we don't use it any longer.
  377. X * 
  378. X * Revision 1.2  88/09/25  02:40:49  jmsellens
  379. X * added message for BAD_VERSION
  380. X * 
  381. X * Revision 1.1  87/08/06  19:06:32  sahayman
  382. X * Initial revision
  383. X * 
  384. X */
  385. X#endif
  386. X
  387. X/* msgtext.c
  388. X   Text of error messages produced by the system
  389. X*/
  390. X
  391. X#include "msg.h"
  392. X
  393. Xchar *errmessages[] = {
  394. X    /* OK */
  395. X    "",
  396. X    /* NOT_ON - user, host */
  397. X    "%s@%s is not signed on",
  398. X    /* NO_WRITE - user, host, ut.u_line, syserr() */
  399. X    "couldn't write to %s@%s (%s): %s",
  400. X    /* BAD_HOST - host */
  401. X    "host '%s' is unknown",
  402. X    /* NO_UTMP - host, syserr() */
  403. X    "couldn't open utmp on host '%s': %s",
  404. X    /* BAD_ARGS - not used I think */
  405. X    "bad argument(s)",
  406. X    /* NO_CONNECT - host syserr() */
  407. X    "couldn't connect to daemon on host '%s': %s (not running?)",
  408. X    /* FATAL - not used I think */
  409. X    "fatal error",
  410. X    /* NO_ACK - host */
  411. X    "didn't receive acknowledgement from host '%s'",
  412. X    /* REMOTE_WRITE - host, syserr() */
  413. X    "error writing to host '%s': %s",
  414. X    /* REMOTE_READ - host, syserr() */
  415. X    "error writing from host '%s': %s",
  416. X    /* MESG_OFF user, host, ut.u_line */
  417. X    "%s@%s (%s) is not receiving messages",
  418. X    /* NO_REPLY user, ut.u_line */
  419. X    "WARNING: Your terminal (%s on %s) cannot be written to",
  420. X    /* TIMEOUT user, host, ut.u_line */
  421. X    "timed out writing to %s@%s (%s) - terminal paging set?",
  422. X    /* ANSWER user, host, line, answerbackmessage */
  423. X    "%s@%s (%s): %s",
  424. X    /* ANS_WARN user, line, answerbackmessage */
  425. X    "%s on %s: Answerback message set to '%s'",
  426. X    /* NO_TTY */
  427. X    "WARNING: You are not on a terminal",
  428. X    /* HOWEVER */
  429. X    "However, %s@%s (%s) received the message",
  430. X    /* NO_STAT - terminal, user, host, syserr() */
  431. X    "Couldn't stat '%s' of %s@%s: %s - message not delivered",
  432. X    /* BAD_VERSION - remote version, our version */
  433. X    "Client version (%d) newer than server (%d) - can't understand you",
  434. X    0
  435. X};
  436. END_OF_FILE
  437. if test 2177 -ne `wc -c <'./Common/errtext.c'`; then
  438.     echo shar: \"'./Common/errtext.c'\" unpacked with wrong size!
  439. fi
  440. # end of './Common/errtext.c'
  441. fi
  442. if test -f './Common/misc.c' -a "${1}" != "-c" ; then 
  443.   echo shar: Will not clobber existing file \"'./Common/misc.c'\"
  444. else
  445. echo shar: Extracting \"'./Common/misc.c'\" \(457 characters\)
  446. sed "s/^X//" >'./Common/misc.c' <<'END_OF_FILE'
  447. X#ifndef lint
  448. Xstatic char *RCSid = "$Header: misc.c,v 1.1 87/08/06 19:06:34 sahayman Exp $";
  449. X#endif
  450. X
  451. X#if 0
  452. X/*
  453. X * $Log:    misc.c,v $
  454. X * Revision 1.1  87/08/06  19:06:34  sahayman
  455. X * Initial revision
  456. X * 
  457. X */
  458. X#endif
  459. X
  460. X/* misc.c
  461. X   miscellaneous routines
  462. X*/
  463. X
  464. X
  465. Xextern int sys_nerr, errno;
  466. Xextern char *sys_errlist[], *sprintf();
  467. X
  468. Xchar *
  469. Xsyserr()
  470. X{
  471. X    static char buf[80];
  472. X
  473. X    return( (errno<sys_nerr) ? sys_errlist[errno] :
  474. X        sprintf(buf,"Unknown error %d", errno) );
  475. X}
  476. END_OF_FILE
  477. if test 457 -ne `wc -c <'./Common/misc.c'`; then
  478.     echo shar: \"'./Common/misc.c'\" unpacked with wrong size!
  479. fi
  480. # end of './Common/misc.c'
  481. fi
  482. if test -f './Common/savemsg.c' -a "${1}" != "-c" ; then 
  483.   echo shar: Will not clobber existing file \"'./Common/savemsg.c'\"
  484. else
  485. echo shar: Extracting \"'./Common/savemsg.c'\" \(3173 characters\)
  486. sed "s/^X//" >'./Common/savemsg.c' <<'END_OF_FILE'
  487. X#ifndef lint
  488. Xstatic char *RCSid = "$Header: /source/users/msg/Common/RCS/savemsg.c,v 1.8 91/08/13 23:57:35 jmsellens Exp $";
  489. X#endif
  490. X
  491. X#if 0
  492. X/*
  493. X * $Log:    savemsg.c,v $
  494. X * Revision 1.8  91/08/13  23:57:35  jmsellens
  495. X * s/eprintf/errprintf/ to avoid libuw clash
  496. X * 
  497. X * Revision 1.7  91/08/13  23:57:05  jmsellens
  498. X * realuser stuff
  499. X * 
  500. X * Revision 1.6  90/12/29  22:01:03  jmsellen
  501. X * Avoid PMBECOME, and handle DUMBSHORT machines
  502. X * 
  503. X * Revision 1.5  88/09/25  03:03:29  jmsellens
  504. X * call syserr() is pmbecome() fails
  505. X * 
  506. X * Revision 1.4  87/10/19  18:29:11  sahayman
  507. X * Use pmbecome() to become different users, since the simple
  508. X * seteuid( old_euid ) after you seteuid (someone) won't work.
  509. X * 
  510. X * Revision 1.2  87/08/06  20:17:31  sahayman
  511. X * Write /usr/tmp/msg.user file by doing a seteuid(user) first, so that
  512. X * it has a chance of working when /usr/tmp is an NFS partition.
  513. X * No longer writes ~/.msg.
  514. X * 
  515. X * Revision 1.1  87/08/06  19:06:40  sahayman
  516. X * Initial revision
  517. X * 
  518. X */
  519. X#endif
  520. X
  521. X#include "msg.h"
  522. X#include <pwd.h>
  523. X#ifdef REALUSER
  524. X#include <mfcf/libuw/standard.h>
  525. X#endif
  526. X
  527. X
  528. Xsavemsg( uid, recipient, sender, msg )
  529. Xint uid;
  530. Xchar *recipient, *sender, *msg;
  531. X{
  532. X    char fname[100];    /* lots o' room */
  533. X    FILE *fp;
  534. X    struct passwd *pwd;
  535. X#ifdef PMBECOME
  536. X    int old_euid = geteuid();
  537. X#endif /* PMBECOME */
  538. X
  539. X    /*
  540. X     * Original code used to write into ~/.msg.  No more.
  541. X     */
  542. X
  543. X    /* truncate the recipient for lookup */
  544. X    if ( strlen(recipient) > sizeof(((struct utmp *)NULL)->ut_name) )
  545. X    recipient[sizeof(((struct utmp *)NULL)->ut_name)] = '\0';
  546. X    if ((pwd = getpwnam(recipient)) == (struct passwd *) NULL) {
  547. X#ifdef DUMBSHORT
  548. X    /* loop through the whole passwd file looking for a
  549. X       truncated match */
  550. X    struct utmp *ut;    /* just for sizeof() */
  551. X    setpwent();
  552. X    while ( (pwd = getpwent()) != (struct passwd *) NULL ) {
  553. X        if ( strncmp(recipient,pwd->pw_name,sizeof(ut->ut_name)) == 0 )
  554. X        break;
  555. X    }
  556. X    if ( pwd == (struct passwd *) NULL )
  557. X        return;
  558. X    recipient = pwd->pw_name;
  559. X#else
  560. X    return;
  561. X#endif
  562. X    }
  563. X#ifdef REALUSER
  564. X    recipient = realuser( pwd );
  565. X#endif
  566. X    
  567. X
  568. X    /* now, put it where it really belongs, in MSGFILE */
  569. X
  570. X#ifdef PMBECOME
  571. X    /*
  572. X     * This seteuid() business is so that this can work
  573. X     * when /usr/tmp is an NFS thingy, and root on a client
  574. X     * can only creat things there owned by -2, so the old
  575. X     * scheme of opening the file and then chowning it wouldn't work.
  576. X     */
  577. X
  578. X#ifdef old
  579. X    if ( seteuid( pwd->pw_uid ) == -1 ) {
  580. X    errprintf("savemsg: Cannot seteuid(%d)", pwd->pw_uid);
  581. X#else
  582. X    if ( pmbecome( pwd->pw_uid ) == -1 ) {
  583. X    errprintf("savemsg: Cannot pmbecome(%d): %s", pwd->pw_uid, syserr());
  584. X#endif
  585. X
  586. X    /*
  587. X     * Keep going, it might work...
  588. X     */
  589. X    }
  590. X#endif /* PMBECOME */
  591. X
  592. X    strcpy( fname, MSGFILE );
  593. X    strcat( fname, recipient );
  594. X
  595. X    (void) unlink( fname );    /* in case it already exists */
  596. X
  597. X    if ( (fp = fopen( fname, "w" ) ) != NULL ) {
  598. X    (void) fchmod( fileno(fp), 0600 );
  599. X    (void) fchown( fileno(fp), pwd->pw_uid, -1 );
  600. X    fprintf( fp, "%s: %s\n", sender, msg );
  601. X    (void) fclose( fp );
  602. X    }
  603. X
  604. X#ifdef PMBECOME
  605. X    if ( pmbecome(0) == -1 )
  606. X    errprintf("savemsg: Cannot pmbecome(0): %s", syserr());
  607. X#endif /* PMBECOME */
  608. X}
  609. END_OF_FILE
  610. if test 3173 -ne `wc -c <'./Common/savemsg.c'`; then
  611.     echo shar: \"'./Common/savemsg.c'\" unpacked with wrong size!
  612. fi
  613. # end of './Common/savemsg.c'
  614. fi
  615. if test ! -d './Include' ; then
  616.     echo shar: Creating directory \"'./Include'\"
  617.     mkdir './Include'
  618. fi
  619. if test -f './Include/msg.h' -a "${1}" != "-c" ; then 
  620.   echo shar: Will not clobber existing file \"'./Include/msg.h'\"
  621. else
  622. echo shar: Extracting \"'./Include/msg.h'\" \(2892 characters\)
  623. sed "s/^X//" >'./Include/msg.h' <<'END_OF_FILE'
  624. X/* msg.h
  625. X   header file for msg and msgd
  626. X*/
  627. X
  628. X/*
  629. X * $Header: /usr/source/users/msg/Include/RCS/msg.h,v 1.9 91/03/08 20:13:16 jmsellens Exp Locker: jmsellens $
  630. X * 
  631. X */
  632. X
  633. X/* Options */
  634. X#include "msgoptions.h"
  635. X
  636. X#include <stdio.h>
  637. X#include <sys/types.h>
  638. X#include <utmp.h>
  639. X#define UTMP    "/etc/utmp"    /* why isn't this in utmp.h?? */
  640. X#ifdef USER_PROCESS
  641. X#define SYSV_UTMP
  642. X#endif
  643. X#include <sys/stat.h>
  644. X#define ALLOW    ((S_IWRITE>>3)|(S_IWRITE>>6))
  645. X#ifdef VARARGS
  646. X#include <varargs.h>
  647. X#endif
  648. X
  649. X#define DEV    "/dev/"
  650. X#define MSGFILE    "/usr/tmp/msg."    /* where to save messages, append userid */
  651. X#define PMSGFILE "/usr/tmp/pmsg." /* where to save outgoing messages */
  652. X#define ANSBACK    "/usr/tmp/mesg."    /* where asnwerback message might be */
  653. X
  654. X#define private        static
  655. X
  656. Xextern char hostname[];
  657. Xextern char *syserr();
  658. X
  659. X/*
  660. X * Following are in network byte order.
  661. X */
  662. Xtypedef struct header {
  663. X    int    slen;    /* sender length */
  664. X    int    ulen;    /* userid length */
  665. X    int    mlen;    /* message length */
  666. X} header;
  667. X
  668. X/* This version header was added after the original version of msg had
  669. X   been installed and was running.  To provide compatibility with versions
  670. X   of msg that do not send a version as the first information, this
  671. X   version struct must be twelve bytes long, and the first int is always
  672. X   a 0, because if it is non-zero you can assume that it is a sender
  673. X   length in a header, and not a version struct.
  674. X*/
  675. Xtypedef union version {
  676. X    header h;
  677. X    struct v {
  678. X    int zero;
  679. X    int vnum;    /* version number */
  680. X    int filler;
  681. X    } v;
  682. X} version;
  683. X#define VERSION        (1)    /* current version */
  684. X
  685. X
  686. Xextern char    *errmessages[];
  687. X/* error codes for message - msgtext.c relies on this ordering */
  688. X#define OK        (0)
  689. X#define VERSION_OK    OK    /* got a version, and we accept it */
  690. X#define NOT_ON        (1)    /* user not signed on */
  691. X#define NO_WRITE    (2)    /* couldn't write to terminal */
  692. X#define BAD_HOST    (3)    /* host doesn't exist */
  693. X#define NO_UTMP        (4)    /* couldn't open /etc/utmp */
  694. X#define BAD_ARGS    (5)    /* bad arguments */
  695. X#define NO_CONNECT    (6)    /* couldn't connect to remote host */
  696. X#define FATAL        (7)    /* fatal error */
  697. X#define NO_ACK        (8)    /* no result from remote host */
  698. X#define REMOTE_WRITE    (9)    /* write error to remote host */
  699. X#define REMOTE_READ    (10)    /* read error from remote host */
  700. X#define MESG_OFF    (11)    /* dest user has mesg n set */
  701. X#define NO_REPLY    (12)    /* can't get replies */
  702. X#define TIMEOUT        (13)    /* timeout while writing to user's terminal */
  703. X#define ANSWER        (14)    /* asnwerback message */
  704. X#define ANS_WARN    (15)    /* user has answerback msg set */
  705. X#define NO_TTY        (16)    /* user is not on a tty */
  706. X#define    HOWEVER        (17)    /* However, another tty was writable. */
  707. X#define NO_STAT        (18)    /* couldn't stat tty */
  708. X#define BAD_VERSION    (19)    /* client newer than server */
  709. X
  710. X#define ERROR_MESSAGE    (99)    /* error message being returned from msgd */
  711. X
  712. X#define FPNULL        ((FILE *)NULL)
  713. X#define CPNULL        ((char *)NULL)
  714. X#define TRUE        (1)
  715. X#define FALSE        (0)
  716. END_OF_FILE
  717. if test 2892 -ne `wc -c <'./Include/msg.h'`; then
  718.     echo shar: \"'./Include/msg.h'\" unpacked with wrong size!
  719. fi
  720. # end of './Include/msg.h'
  721. fi
  722. if test -f './Include/msgoptions.h' -a "${1}" != "-c" ; then 
  723.   echo shar: Will not clobber existing file \"'./Include/msgoptions.h'\"
  724. else
  725. echo shar: Extracting \"'./Include/msgoptions.h'\" \(1588 characters\)
  726. sed "s/^X//" >'./Include/msgoptions.h' <<'END_OF_FILE'
  727. X/* msgoptions.h
  728. X   separate options file, so I can #inlcude it in an Imakefile
  729. X*/
  730. X
  731. X/*
  732. X * $Header: /usr/source/users/msg/Include/RCS/msg.h,v 1.9 91/03/08 20:13:16 jmsellens Exp Locker: jmsellens $
  733. X * 
  734. X */
  735. X
  736. X/* Options */
  737. X/* define PMBECOME if you want to use the Waterloo pmbecome() routine
  738. X   which allows you to seteuid() to a user, and seteuid() back to root
  739. X   later.  Only needed if the MSGFILE is on a partition that root can't
  740. X   write, such as on pre 4.0 SunOS diskless clients. */
  741. X/* #define PMBECOME */
  742. X
  743. X/* define SAVEMSG to save received messages in MSGFILE */
  744. X#define SAVEMSG
  745. X
  746. X/* define ANSWERBACK to allow the use of answerback files set up by
  747. X   mesg to send back to the sender when a message is received. */
  748. X#define ANSWERBACK
  749. X
  750. X/* define REMOTE to always use the daemon to deliver instead of doing
  751. X   local delivery when possible.  This means msg doesn't have to be
  752. X   setuid/setgid, but it's also slower. */
  753. X/* #define REMOTE */
  754. X
  755. X/* define VARARGS if you have the varargs stuff, including vprintf and
  756. X   friends. */
  757. X#define VARARGS
  758. X
  759. X/* define DUMBSHORT if you're silly enough to have long userids in the
  760. X   passwd file, but short userids everywhere else.  We were silly enough
  761. X   to be doing this on our MIPS machines ... */
  762. X/* #define DUMBSHORT */
  763. X
  764. X/* define REALUSER if you want to use the MFCF realuser() routine to find
  765. X   out your "real" campus-wide userid and use that as the return address.
  766. X   This won't be useful outside Waterloo, and I hope I remembered to remove
  767. X   the "-luw" from the Makefile before sending it into the outside world. */
  768. X/* #define REALUSER */
  769. END_OF_FILE
  770. if test 1588 -ne `wc -c <'./Include/msgoptions.h'`; then
  771.     echo shar: \"'./Include/msgoptions.h'\" unpacked with wrong size!
  772. fi
  773. # end of './Include/msgoptions.h'
  774. fi
  775. if test -f './Makefile' -a "${1}" != "-c" ; then 
  776.   echo shar: Will not clobber existing file \"'./Makefile'\"
  777. else
  778. echo shar: Extracting \"'./Makefile'\" \(385 characters\)
  779. sed "s/^X//" >'./Makefile' <<'END_OF_FILE'
  780. X# Makes msg and msgd and mesg, one hopes.
  781. X
  782. XTOP    = /software/users
  783. XBINDIR    = $(TOP)/bin
  784. XSERVDIR    = $(TOP)/servers
  785. XMANDIR    = $(TOP)/man
  786. X
  787. XMACROS    = BINDIR=$(BINDIR) SERVDIR=$(SERVDIR) MANDIR=$(MANDIR)
  788. X
  789. Xall\
  790. Xclean\
  791. Xinstall:
  792. X    cd msg && $(MAKE) $(MFLAGS) $(MACROS) $@
  793. X    cd msgd && $(MAKE) $(MFLAGS) $(MACROS) $@
  794. X    cd mesg && $(MAKE) $(MFLAGS) $(MACROS) $@
  795. X    cd Man && $(MAKE) $(MFLAGS) $(MACROS) $@
  796. END_OF_FILE
  797. if test 385 -ne `wc -c <'./Makefile'`; then
  798.     echo shar: \"'./Makefile'\" unpacked with wrong size!
  799. fi
  800. # end of './Makefile'
  801. fi
  802. if test ! -d './Man' ; then
  803.     echo shar: Creating directory \"'./Man'\"
  804.     mkdir './Man'
  805. fi
  806. if test -f './Man/Makefile' -a "${1}" != "-c" ; then 
  807.   echo shar: Will not clobber existing file \"'./Man/Makefile'\"
  808. else
  809. echo shar: Extracting \"'./Man/Makefile'\" \(448 characters\)
  810. sed "s/^X//" >'./Man/Makefile' <<'END_OF_FILE'
  811. XMANDIR    = /software/users/man
  812. XMANUSER    = bin
  813. XMANMODE    = 444
  814. X
  815. Xall:
  816. X    echo All made in Man
  817. Xclean:
  818. X    echo All clean in Man
  819. Xinstall:
  820. X    cp -p msg.1 $(MANDIR)/man1
  821. X    chown $(MANUSER) $(MANDIR)/man1/msg.1
  822. X    chmod $(MANMODE) $(MANDIR)/man1/msg.1
  823. X    cp -p msgd.8 $(MANDIR)/man8
  824. X    chown $(MANUSER) $(MANDIR)/man8/msgd.8
  825. X    chmod $(MANMODE) $(MANDIR)/man8/msgd.8
  826. X    cp -p mesg.8 $(MANDIR)/man8
  827. X    chown $(MANUSER) $(MANDIR)/man8/mesg.8
  828. X    chmod $(MANMODE) $(MANDIR)/man8/mesg.8
  829. END_OF_FILE
  830. if test 448 -ne `wc -c <'./Man/Makefile'`; then
  831.     echo shar: \"'./Man/Makefile'\" unpacked with wrong size!
  832. fi
  833. # end of './Man/Makefile'
  834. fi
  835. if test -f './Man/mesg.1' -a "${1}" != "-c" ; then 
  836.   echo shar: Will not clobber existing file \"'./Man/mesg.1'\"
  837. else
  838. echo shar: Extracting \"'./Man/mesg.1'\" \(1937 characters\)
  839. sed "s/^X//" >'./Man/mesg.1' <<'END_OF_FILE'
  840. X.\" Copyright (c) 1987 Regents of the University of California.
  841. X.\" All rights reserved.
  842. X.\"
  843. X.\" Redistribution and use in source and binary forms are permitted
  844. X.\" provided that the above copyright notice and this paragraph are
  845. X.\" duplicated in all such forms and that any documentation,
  846. X.\" advertising materials, and other materials related to such
  847. X.\" distribution and use acknowledge that the software was developed
  848. X.\" by the University of California, Berkeley.  The name of the
  849. X.\" University may not be used to endorse or promote products derived
  850. X.\" from this software without specific prior written permission.
  851. X.\" THIS SOFTWARE IS PROVIDED ``AS IS'' AND WITHOUT ANY EXPRESS OR
  852. X.\" IMPLIED WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED
  853. X.\" WARRANTIES OF MERCHANTIBILITY AND FITNESS FOR A PARTICULAR PURPOSE.
  854. X.\"
  855. X.\"     @(#)mesg.1      6.3 (Berkeley) 7/9/88
  856. X.\"
  857. X.TH MESG 1 "18 July 1983"
  858. X.SH NAME
  859. Xmesg \- permit or deny messages
  860. X.SH SYNOPSIS
  861. X.B mesg
  862. X[
  863. X.B n
  864. X] [
  865. X.B y
  866. X]
  867. X[answerback message]
  868. X.SH DESCRIPTION
  869. X.I Mesg
  870. Xwith argument
  871. X.B n
  872. Xforbids messages via
  873. X.I  write
  874. Xand
  875. X.IR talk (1)
  876. Xby revoking non-user
  877. Xwrite permission on the user's terminal.
  878. X.I Mesg
  879. Xwith argument
  880. X.B y
  881. Xreinstates permission.
  882. XAll by itself,
  883. X.I mesg
  884. Xreports the current state and answerback message without changing it.
  885. X.PP
  886. XThe answerback message
  887. Xis used as an automatic response to anyone who tries to send you a msg.
  888. XThe existing answerback message is removed on subsequent
  889. X.I mesg
  890. Xcommand invocations (except when no arguments are given).
  891. X.SH EXAMPLE
  892. Xmesg n Please send me mail instead.
  893. X.SH BUGS
  894. X.I mesg
  895. Xwill not work within a
  896. X.IR script (1)
  897. Xsession because there is no way for it to find out what terminal
  898. Xyou are really signed on to.
  899. X.SH FILES
  900. X/dev/tty*
  901. X.br
  902. X/usr/tmp/mesg.tty*
  903. X.SH "SEE ALSO"
  904. Xwrite(1), talk(1)
  905. X.SH DIAGNOSTICS
  906. XExit status is 0 if messages are receivable,
  907. X1 if not, 2 on error.
  908. X.SH NOTE
  909. XAnswerback messages are a Waterloo addition.
  910. END_OF_FILE
  911. if test 1937 -ne `wc -c <'./Man/mesg.1'`; then
  912.     echo shar: \"'./Man/mesg.1'\" unpacked with wrong size!
  913. fi
  914. # end of './Man/mesg.1'
  915. fi
  916. if test -f './Man/msg.1' -a "${1}" != "-c" ; then 
  917.   echo shar: Will not clobber existing file \"'./Man/msg.1'\"
  918. else
  919. echo shar: Extracting \"'./Man/msg.1'\" \(3411 characters\)
  920. sed "s/^X//" >'./Man/msg.1' <<'END_OF_FILE'
  921. X.TH MSG 1 "University of Waterloo"
  922. X.SH NAME
  923. Xmsg \- write a short message to other users
  924. X.SH SYNOPSIS
  925. X.B msg
  926. X[
  927. X.B \-l
  928. X]
  929. X[
  930. X.B \-m
  931. X.I message
  932. X]
  933. X[
  934. X.B \-p
  935. X]
  936. X[
  937. X.B \-r
  938. X]
  939. X[
  940. X.B \-t
  941. X]
  942. Xuser ...
  943. X.SH DESCRIPTION
  944. X.I Msg
  945. Xwrites a one-line message to a given set of users.
  946. XIf a user is logged in more than once, each instance of that user will receive
  947. Xthe message.
  948. X.PP
  949. XPrevious versions of
  950. X.I msg
  951. Xallowed the last argument to be the message.  This confusing behaviour
  952. Xis no longer available.
  953. X.PP
  954. XThe message is preceded by a beep,
  955. Xthe login name of the sender,
  956. Xand the name of the sender's machine.
  957. XIf the sender is set-userid to someone other than the super-user,
  958. Xthen the real (set-userid) name is printed in parentheses.
  959. XReplies should use the login name, not the parenthesized (set-userid) name,
  960. Xsince the login name is the way
  961. X.I msg
  962. Xfinds people.
  963. X.PP
  964. X.I Msg
  965. Xworks across machines, as long as the remote machine is running the
  966. X.IR msgd (8)
  967. Xmessage daemon.
  968. XTo do this,
  969. X.I user
  970. Xshould be of the form
  971. X.I person@machine
  972. X(or the old-style
  973. X.I machine!person
  974. X).
  975. X.PP
  976. XIt is very annoying to receive a message just before your screen clears,
  977. Xmaking it impossible to read the message.
  978. XTo help alleviate this problem,
  979. X.I msg
  980. Xwill save a copy of the message and you can use the
  981. X.I -l
  982. Xoption to repeat the last message you received.
  983. X.PP
  984. XIt is also annoying to discover a message on your screen but not know
  985. Xwhen it was sent.  Use \fB\-t\fP to find out.
  986. X.SH OPTIONS
  987. X.TP 10
  988. X.B \-r
  989. XIf the
  990. X.BR \-r ,
  991. Xoption is given,
  992. X.I msg
  993. Xwill look in the file
  994. X.I /usr/tmp/msg.userid
  995. Xfile to find out the last person who sent you a message,
  996. Xand assume you want to reply to them.
  997. X(Additional recipients can still be specified, so the same
  998. Xrules apply about which arguments are messages and which are users.
  999. XThe easiest thing to use is
  1000. X.I "msg -r"
  1001. Xwith no other arguments; type the reply on the next line.)
  1002. X.TP
  1003. X.B \-l
  1004. XList the last message received.
  1005. XThis simply shows the file
  1006. X.I /usr/tmp/msg.userid
  1007. Xso that you don't have to remember the name.
  1008. X.I "msg -lr"
  1009. Xis a handy way to show the last message and prompt for a reply.
  1010. X.TP
  1011. X.B \-t
  1012. XShow the time that the last message was received.  Handy combinations are
  1013. X.B \-tl
  1014. Xand
  1015. X.B \-tlr.
  1016. X.TP
  1017. X.B \-p
  1018. XUse the text of the previous message you sent (saved in the file
  1019. X.IR /usr/tmp/pmsg.userid )
  1020. Xas the text of this message.  This is handy if you mistyped someone's
  1021. Xuserid, and typed a long message only to have it fail.
  1022. X.PP
  1023. X.I Msg
  1024. Xobeys the restrictions of
  1025. X.IR mesg (1).
  1026. X.SH "SEE ALSO"
  1027. Xwrite(1), mail(1), talk(1), msgd(8)
  1028. X.SH EXAMPLES
  1029. X.TP 10
  1030. X% msg -m 'This is the message in quotes.' user1 user2
  1031. XQuoting a string makes it one argument as far as Unix is concerned.
  1032. X.TP 10
  1033. X% msg user1 user2
  1034. X<type the message here, on the next line>
  1035. X.TP 10
  1036. X% msg -r
  1037. X<Type a reply here to the last person who sent you a msg.>
  1038. X.TP 10
  1039. X% msg -r -m 'Or you can put the reply here.'
  1040. X.SH FILES
  1041. X.TP
  1042. X/usr/tmp/msg.userid
  1043. XContains the last message received.
  1044. X.TP
  1045. X/usr/tmp/pmsg.userid
  1046. XContains the text of the previous message sent or attempted.
  1047. X.TP
  1048. X/usr/tmp/mesg.userid
  1049. XAnswerback message - set by mesg(1).
  1050. X.SH AUTHOR
  1051. XThe staff of the Math Faculty Computing Facility at the University
  1052. Xof Waterloo, Waterloo, Ontario Canada.  Bug reports can be sent
  1053. Xto either or both of John Sellens (jmsellens@watmath.waterloo.edu)
  1054. Xor uw.mfcf.bugs@watmath.waterloo.edu.
  1055. X.SH COPYRIGHT
  1056. XCopyright 1988, 1989, 1990 University of Waterloo
  1057. X.br
  1058. XRedistribution is permitted.
  1059. END_OF_FILE
  1060. if test 3411 -ne `wc -c <'./Man/msg.1'`; then
  1061.     echo shar: \"'./Man/msg.1'\" unpacked with wrong size!
  1062. fi
  1063. # end of './Man/msg.1'
  1064. fi
  1065. if test -f './Man/msgd.8' -a "${1}" != "-c" ; then 
  1066.   echo shar: Will not clobber existing file \"'./Man/msgd.8'\"
  1067. else
  1068. echo shar: Extracting \"'./Man/msgd.8'\" \(728 characters\)
  1069. sed "s/^X//" >'./Man/msgd.8' <<'END_OF_FILE'
  1070. X.TH MSGD 8 "University of Waterloo"
  1071. X.SH NAME
  1072. Xmsgd \- remote message daemon
  1073. X.SH DESCRIPTION
  1074. X.I Msgd
  1075. Xaccepts connections from remote
  1076. X.IR msg (1)
  1077. Xcommands for delivery to users on the local system.
  1078. X.PP
  1079. X.I Msgd
  1080. Xis normally run under
  1081. X.IR inetd (8).
  1082. X.SH FILES
  1083. X.IP /etc/services
  1084. Xdefines which port
  1085. X.I msgd
  1086. Xwill use
  1087. X.IP /etc/inetd.conf
  1088. Xconfig file for
  1089. X.I inetd
  1090. X.SH "SEE ALSO"
  1091. Xmsg(1), mesg(1)
  1092. X.SH AUTHOR
  1093. XThe staff of the Math Faculty Computing Facility at the University
  1094. Xof Waterloo, Waterloo, Ontario Canada.  Bug reports can be sent
  1095. Xto either or both of John Sellens (jmsellens@watmath.waterloo.edu)
  1096. Xor uw.mfcf.bugs@watmath.waterloo.edu.
  1097. X.SH COPYRIGHT
  1098. XCopyright 1988, 1989, 1990 University of Waterloo
  1099. X.br
  1100. XRedistribution is permitted.
  1101. END_OF_FILE
  1102. if test 728 -ne `wc -c <'./Man/msgd.8'`; then
  1103.     echo shar: \"'./Man/msgd.8'\" unpacked with wrong size!
  1104. fi
  1105. # end of './Man/msgd.8'
  1106. fi
  1107. if test -f './inetd.conf' -a "${1}" != "-c" ; then 
  1108.   echo shar: Will not clobber existing file \"'./inetd.conf'\"
  1109. else
  1110. echo shar: Extracting \"'./inetd.conf'\" \(61 characters\)
  1111. sed "s/^X//" >'./inetd.conf' <<'END_OF_FILE'
  1112. Xmsg    stream    tcp    nowait    root    /software/users/servers/msgd    msgd
  1113. END_OF_FILE
  1114. if test 61 -ne `wc -c <'./inetd.conf'`; then
  1115.     echo shar: \"'./inetd.conf'\" unpacked with wrong size!
  1116. fi
  1117. # end of './inetd.conf'
  1118. fi
  1119. if test ! -d './mesg' ; then
  1120.     echo shar: Creating directory \"'./mesg'\"
  1121.     mkdir './mesg'
  1122. fi
  1123. if test -f './mesg/Makefile' -a "${1}" != "-c" ; then 
  1124.   echo shar: Will not clobber existing file \"'./mesg/Makefile'\"
  1125. else
  1126. echo shar: Extracting \"'./mesg/Makefile'\" \(378 characters\)
  1127. sed "s/^X//" >'./mesg/Makefile' <<'END_OF_FILE'
  1128. X# Needs to be setuid root so we can remove others' answerback files
  1129. X
  1130. XBINDIR    = /software/users/bin
  1131. XMANDIR    = /software/users/man
  1132. X
  1133. XNAME    = mesg
  1134. XOWNER=root
  1135. XGROUP=staff
  1136. XMODE=4755
  1137. X
  1138. XOBJECT    = mesg.o
  1139. X
  1140. Xall: $(NAME)
  1141. X
  1142. X$(NAME): $(OBJECT)
  1143. X    cc -o $(NAME) $(OBJECT)
  1144. X
  1145. Xinstall: $(NAME)
  1146. X    install -s -o $(OWNER) -g $(GROUP) -m $(MODE) $(NAME) $(BINDIR)/$(NAME)
  1147. X
  1148. Xclean:
  1149. X    rm -f a.out core *.o $(NAME)
  1150. END_OF_FILE
  1151. if test 378 -ne `wc -c <'./mesg/Makefile'`; then
  1152.     echo shar: \"'./mesg/Makefile'\" unpacked with wrong size!
  1153. fi
  1154. # end of './mesg/Makefile'
  1155. fi
  1156. if test -f './mesg/mesg.c' -a "${1}" != "-c" ; then 
  1157.   echo shar: Will not clobber existing file \"'./mesg/mesg.c'\"
  1158. else
  1159. echo shar: Extracting \"'./mesg/mesg.c'\" \(4528 characters\)
  1160. sed "s/^X//" >'./mesg/mesg.c' <<'END_OF_FILE'
  1161. X/*
  1162. X * Copyright (c) 1987 Regents of the University of California.
  1163. X * All rights reserved.
  1164. X *
  1165. X * Redistribution and use in source and binary forms are permitted
  1166. X * provided that the above copyright notice and this paragraph are
  1167. X * duplicated in all such forms and that any documentation,
  1168. X * advertising materials, and other materials related to such
  1169. X * distribution and use acknowledge that the software was developed
  1170. X * by the University of California, Berkeley.  The name of the
  1171. X * University may not be used to endorse or promote products derived
  1172. X * from this software without specific prior written permission.
  1173. X * THIS SOFTWARE IS PROVIDED ``AS IS'' AND WITHOUT ANY EXPRESS OR
  1174. X * IMPLIED WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED
  1175. X * WARRANTIES OF MERCHANTIBILITY AND FITNESS FOR A PARTICULAR PURPOSE.
  1176. X */
  1177. X
  1178. X#ifndef lint
  1179. Xchar copyright[] =
  1180. X"@(#) Copyright (c) 1987 Regents of the University of California.\n\
  1181. X All rights reserved.\n";
  1182. X#endif /* not lint */
  1183. X
  1184. Xstatic char *sccsid = "@(#)mesg.c    4.2 (Berkeley) 10/18/80";
  1185. X/*
  1186. X * mesg -- set current tty to accept or
  1187. X *    forbid write permission.
  1188. X *
  1189. X *    mesg [yn] "answerback message"
  1190. X *        y allow messages
  1191. X *        n forbid messages
  1192. X *        answerback is what the other guy gets told (Waterloo)
  1193. X *        needs to be setuid root to get rid of other people's
  1194. X *        old answerback message files
  1195. X *
  1196. X */
  1197. X
  1198. X#include <stdio.h>
  1199. X#include <sys/types.h>
  1200. X#include <sys/stat.h>
  1201. X#include <utmp.h>
  1202. X#include <pwd.h>
  1203. X
  1204. X#define ANSWERBACK_FMT    "/usr/tmp/mesg.%s"
  1205. X
  1206. Xmain(argc, argv)
  1207. X    char **argv;
  1208. X{
  1209. X    int uid, mode, r=0;
  1210. X    char *tty, *p, *rindex(), *ttyname();
  1211. X    FILE *fp;
  1212. X    int i_own_answerback = 0;
  1213. X    struct stat sbuf;
  1214. X    struct passwd *pw;
  1215. X    char answerback[200];
  1216. X
  1217. X    (void) umask(022);    /* so we can read answerback file */
  1218. X    tty = ttyname(2);
  1219. X    if (tty == 0)
  1220. X        error("Cannot determine name of current terminal", (char *)0);
  1221. X    if ( (p=rindex(tty,'/')) != NULL )
  1222. X        p++;
  1223. X    else
  1224. X        p = tty;
  1225. X    /*
  1226. X     * If this isn't a login session, use of mesg is meaningless.
  1227. X     */
  1228. X    uid = getuid();
  1229. X    pw = getpwuid(uid);
  1230. X    if (pw == NULL) {
  1231. X        fprintf(stderr, "mesg: Can't find your uid (%d) in the password file\n", uid);
  1232. X        exit(2);
  1233. X    }
  1234. X    if (!in_utmp(pw->pw_name, p)) {
  1235. X        fprintf(stderr, "mesg: Current terminal session on %s is not a login session\n", tty);
  1236. X        exit(2);
  1237. X    }
  1238. X    /* find name of answerback file */
  1239. X    (void) sprintf( answerback, ANSWERBACK_FMT, p );
  1240. X    /* Now make sure that if the answerback file exists, it belongs to
  1241. X       the current user */
  1242. X    if ( lstat( answerback, &sbuf ) == 0 ) {
  1243. X        if (sbuf.st_uid == uid)
  1244. X            i_own_answerback = 1;
  1245. X        else
  1246. X            (void) unlink(answerback);
  1247. X    }
  1248. X    if(stat(tty, &sbuf) < 0) error("cannot stat", tty);
  1249. X    /*
  1250. X     * must be root before here so we can get rid of other persons
  1251. X     * answerback file since sticky bit is on tmp directory.
  1252. X     * must be real user after here so he cant read/write *any* file
  1253. X     * by creating a link in the tmp directory.
  1254. X     */
  1255. X    setuid(uid);
  1256. X    if(argc < 2) {
  1257. X        if(sbuf.st_mode & 020)
  1258. X            printf( "is y\n" );
  1259. X        else {    r=1;
  1260. X            printf( "is n\n" );
  1261. X        }
  1262. X        if (i_own_answerback) {
  1263. X            if ( (fp=fopen(answerback,"r")) != NULL ) {
  1264. X                int c;
  1265. X                while ( (c=getc(fp)) != EOF )
  1266. X                    putc( c, stdout );
  1267. X                (void) fclose( fp );
  1268. X            } else
  1269. X                error("Can't read answerback file", answerback);
  1270. X        }
  1271. X    } else {
  1272. X        if (i_own_answerback)
  1273. X            (void) unlink(answerback);
  1274. X        if ( argv[1][0] == 'y' ) {
  1275. X            mode = sbuf.st_mode | 020;
  1276. X        } else if ( argv[1][0] == 'n' ) {
  1277. X            mode = sbuf.st_mode & ~022;
  1278. X            r = 1;
  1279. X        } else
  1280. X            error("usage: mesg [yn] [answerback message]", (char *)0);
  1281. X        if (chmod(tty, mode) < 0)
  1282. X            error("cannot change modes", tty);
  1283. X        if ( argc > 2 ) {    /* write answerback message */
  1284. X            int i;
  1285. X            if ( (fp=fopen(answerback,"w")) == (FILE *)NULL )
  1286. X                error("Couldn't write answerback file", answerback);
  1287. X            for ( i=2; i<argc; i++ ) {
  1288. X                if ( i>2 )
  1289. X                    putc( ' ', fp );
  1290. X                fputs( argv[i], fp );
  1291. X            }
  1292. X            putc( '\n', fp );
  1293. X            (void) fclose( fp );
  1294. X        }
  1295. X    }
  1296. X    exit(r);
  1297. X}
  1298. X
  1299. Xerror(s, arg)
  1300. Xchar *s, *arg;
  1301. X{
  1302. X    fprintf(stderr,"mesg: %s", s);
  1303. X    if (arg)
  1304. X        perror(arg);
  1305. X    else
  1306. X        putc('\n', stderr);
  1307. X    exit(2);
  1308. X}
  1309. X
  1310. X/*
  1311. X * Does the given (user,tty) pair appear in the utmp file?
  1312. X */
  1313. Xin_utmp(user, tty)
  1314. X    char *user, *tty;
  1315. X{
  1316. X    FILE *fp;
  1317. X    struct utmp utmp;
  1318. X
  1319. X    if ((fp = fopen("/etc/utmp", "r")) == NULL)
  1320. X        return 0;
  1321. X    while (fread((char *)&utmp, sizeof utmp, 1, fp) == 1) {
  1322. X        if (strncmp(user, utmp.ut_name, sizeof utmp.ut_name) == 0 &&
  1323. X            strncmp(tty, utmp.ut_line, sizeof utmp.ut_line) == 0) {
  1324. X#ifdef USER_PROCESS
  1325. X            if ( utmp.ut_type != USER_PROCESS )
  1326. X                continue;
  1327. X#endif
  1328. X            fclose(fp);
  1329. X            return 1;
  1330. X        }
  1331. X    }
  1332. X    fclose(fp);
  1333. X    return 0;
  1334. X}
  1335. END_OF_FILE
  1336. if test 4528 -ne `wc -c <'./mesg/mesg.c'`; then
  1337.     echo shar: \"'./mesg/mesg.c'\" unpacked with wrong size!
  1338. fi
  1339. # end of './mesg/mesg.c'
  1340. fi
  1341. if test ! -d './msg' ; then
  1342.     echo shar: Creating directory \"'./msg'\"
  1343.     mkdir './msg'
  1344. fi
  1345. if test -f './msg/Makefile' -a "${1}" != "-c" ; then 
  1346.   echo shar: Will not clobber existing file \"'./msg/Makefile'\"
  1347. else
  1348. echo shar: Extracting \"'./msg/Makefile'\" \(927 characters\)
  1349. sed "s/^X//" >'./msg/Makefile' <<'END_OF_FILE'
  1350. X# Needs to be setuid root so that msg save files can be made and chown'd.
  1351. X# Needs to be setgid tty so that we can write to ttys in /dev
  1352. X
  1353. XBINDIR    = /software/users/bin
  1354. XMANDIR    = /software/users/man
  1355. X
  1356. XNAME    = msg
  1357. XOWNER=root
  1358. XGROUP=tty
  1359. XMODE=6555
  1360. XCFLAGS= -I../Include $(DBX)
  1361. X
  1362. XOBJECT    = msg.o remote.o deliver.o misc.o errtext.o savemsg.o answerback.o
  1363. X
  1364. Xall: $(NAME)
  1365. X
  1366. X$(NAME): $(OBJECT)
  1367. X    cc -o $(NAME) $(OBJECT)
  1368. X
  1369. Xinstall: $(NAME)
  1370. X    install -s -o $(OWNER) -g $(GROUP) -m $(MODE) $(NAME) $(BINDIR)/$(NAME)
  1371. X
  1372. Xclean:
  1373. X    rm -f a.out core *.o $(NAME)
  1374. X
  1375. X$(OBJECT): ../Include/msg.h ../Include/msgoptions.h
  1376. X
  1377. Xanswerback.o: ../Common/answerback.c
  1378. X    cc $(CFLAGS) -c ../Common/answerback.c
  1379. X
  1380. Xdeliver.o: ../Common/deliver.c
  1381. X    cc $(CFLAGS) -c ../Common/deliver.c
  1382. X
  1383. Xerrtext.o: ../Common/errtext.c
  1384. X    cc $(CFLAGS) -c ../Common/errtext.c
  1385. X
  1386. Xmisc.o: ../Common/misc.c
  1387. X    cc $(CFLAGS) -c ../Common/misc.c
  1388. X
  1389. Xsavemsg.o: ../Common/savemsg.c
  1390. X    cc $(CFLAGS) -c ../Common/savemsg.c
  1391. END_OF_FILE
  1392. if test 927 -ne `wc -c <'./msg/Makefile'`; then
  1393.     echo shar: \"'./msg/Makefile'\" unpacked with wrong size!
  1394. fi
  1395. # end of './msg/Makefile'
  1396. fi
  1397. if test -f './msg/msg.c' -a "${1}" != "-c" ; then 
  1398.   echo shar: Will not clobber existing file \"'./msg/msg.c'\"
  1399. else
  1400. echo shar: Extracting \"'./msg/msg.c'\" \(12537 characters\)
  1401. sed "s/^X//" >'./msg/msg.c' <<'END_OF_FILE'
  1402. X/*
  1403. X * $Header: /source/users/msg/msg/RCS/msg.c,v 1.24 91/08/18 18:37:29 dgharriss Exp $
  1404. X */
  1405. X
  1406. X/*
  1407. X * msg.c
  1408. X * MSG re-written to use a daemon
  1409. X * John Sellens, University of Waterloo
  1410. X */
  1411. X
  1412. X#include "msg.h"
  1413. X#include <pwd.h>
  1414. X#include <strings.h>
  1415. X
  1416. X#ifdef REALUSER
  1417. X#include <mfcf/libuw/standard.h>
  1418. X#endif
  1419. X
  1420. X/* global */ char    hostname[80];
  1421. Xprivate    char    *progname;
  1422. X#define USERIDSPACE    (80)    /* lots of room */
  1423. Xprivate    char    sender[USERIDSPACE];
  1424. Xprivate    char    loginname[USERIDSPACE];
  1425. Xprivate    int    uid;    /* effective */
  1426. Xprivate    int    ruid;    /* real */
  1427. X
  1428. Xprivate    char     msg_file[80];
  1429. Xprivate    char     pmsg_file[80];
  1430. X
  1431. Xextern    char    *syserr();
  1432. Xextern    char    *ttyname();
  1433. X
  1434. Xprivate    int    getsender(), sendmsg();
  1435. Xprivate    void    replywarn();
  1436. Xprivate    void    usage();
  1437. Xprivate    void    getprevious();
  1438. Xprivate    void    putprevious();
  1439. Xextern    void    fatal();
  1440. X
  1441. X#define    SU    (0)    /* uid of super-user */
  1442. X
  1443. Xmain( argc, argv )
  1444. Xint argc;
  1445. Xchar *argv[];
  1446. X{
  1447. X    register int i;
  1448. X    register int exitcode = 0;
  1449. X    int fromroot;
  1450. X    int useprevious = 0;    /* send previous text as msg */
  1451. X    int cmdlinemsg = 0;        /* msg is on cmd line */
  1452. X    char *p;
  1453. X    char message[1024];            /* to hold message */
  1454. X    char rawmsg[1024];            /* to hold unclean message */
  1455. X    char *tname;            /* name of current tty */
  1456. X    char *reply = NULL, *reply_to();
  1457. X
  1458. X
  1459. X    int c;
  1460. X    extern int optind;
  1461. X    extern char *optarg;
  1462. X
  1463. X
  1464. X    progname = argv[0];
  1465. X    if ( argc == 1 )
  1466. X    usage();
  1467. X
  1468. X    if ( gethostname( hostname, (int)sizeof(hostname) ) )
  1469. X    fatal( "Couldn't gethostname(): %s", syserr() );
  1470. X
  1471. X    fromroot = getsender();
  1472. X    strcpy( msg_file, MSGFILE );
  1473. X    strcat( msg_file, loginname );
  1474. X    strcpy( pmsg_file, PMSGFILE );
  1475. X    strcat( pmsg_file, loginname );
  1476. X
  1477. X    while (( c = getopt(argc, argv, "lm:prt")) != EOF ) {
  1478. X    switch( c ) {
  1479. X    case 'l':
  1480. X        list_msg();
  1481. X        break;
  1482. X    case 'm':
  1483. X        strcpy( rawmsg, optarg ); /* hope they don't have a giant msg */
  1484. X        cmdlinemsg++;
  1485. X        break;
  1486. X    case 'p':
  1487. X        useprevious++;
  1488. X        break;
  1489. X    case 'r':
  1490. X        if ( (reply = reply_to()) == NULL ) {
  1491. X        fatal( "Nobody to reply to in last message file '%s'",
  1492. X            msg_file );
  1493. X        }
  1494. X        break;
  1495. X    case 't':
  1496. X        list_msgtime();
  1497. X        break;
  1498. X    default:
  1499. X        usage();
  1500. X    }
  1501. X    }
  1502. X    if ( useprevious && cmdlinemsg )
  1503. X    fatal( "-m and -p can't be used together" );
  1504. X
  1505. X    /* Tell 'em now so that the lastmsg comes before you get the replying
  1506. X       message, and tell them so they know who they're sending to, in
  1507. X       case it's wrong. */
  1508. X    if ( reply != NULL )
  1509. X    errprintf("Replying to '%s'", reply);
  1510. X
  1511. X    /*
  1512. X     * Simpler to pretend the options weren't there. Skip over 'em.
  1513. X     * argv/argc is now a vector of user names.
  1514. X     */
  1515. X    argc -= optind;
  1516. X    argv += optind;
  1517. X
  1518. X
  1519. X    if ( (cmdlinemsg||useprevious) && reply == NULL && argc == 0 )
  1520. X    fatal( "No one to send message to" );
  1521. X
  1522. X    /*
  1523. X     * Quietly exit if no recipients and no reply.  This covers the case
  1524. X     * where all we got was the -l option.
  1525. X     */
  1526. X    if ( reply == NULL && argc == 0 )
  1527. X    exit(0);
  1528. X
  1529. X    /* Old behaviour used - as last argument to indicate msg on stdin */
  1530. X    if ( strcmp("-", argv[argc-1]) == 0 ) {
  1531. X    errprintf( "'-' as last argument is obsolete - ignored" );
  1532. X    argc--;
  1533. X    }
  1534. X
  1535. X    if ( useprevious ) {
  1536. X    getprevious( rawmsg, (int)sizeof(rawmsg) );
  1537. X    } else if ( ! cmdlinemsg ) {
  1538. X    if ( fgets( rawmsg, (int)sizeof(rawmsg), stdin ) == NULL ) {
  1539. X        /* assume user changed their mind */
  1540. X        return(0);
  1541. X    }
  1542. X    p = index(rawmsg, '\n');
  1543. X    if (p == NULL)
  1544. X        errprintf("Message truncated to %d characters.", sizeof(rawmsg) );
  1545. X    else
  1546. X        *p = NULL;
  1547. X    }
  1548. X
  1549. X    if ( *rawmsg == '\0' )    /* No message to send. */
  1550. X    return(0);
  1551. X    sanitize( rawmsg, message );
  1552. X
  1553. X    if ( useprevious )
  1554. X    printf( "Sending: %s\n", message );
  1555. X    else
  1556. X    putprevious( message );
  1557. X
  1558. X    if( (tname=ttyname(0)) || (tname=ttyname(1)) || (tname=ttyname(2)) )
  1559. X    replywarn(tname);    /* warn if can't get replies on this tty */
  1560. X#if 0
  1561. X    /* Is this a good idea?  -IAN! */
  1562. X    else
  1563. X    errmsg( NO_TTY );
  1564. X#endif
  1565. X
  1566. X    /*
  1567. X     * Send a reply if -r was used, also send to all other
  1568. X     * recipients on the command line.
  1569. X     */
  1570. X
  1571. X    if ( reply != NULL && sendmsg(reply, message, fromroot) != OK )
  1572. X    exitcode++;
  1573. X
  1574. X    while ( --argc >= 0 ) {
  1575. X    /* sendmsg() will destroy the argv[i] */
  1576. X    if ( sendmsg( *argv++, message, fromroot ) != OK )
  1577. X        exitcode++;
  1578. X    }
  1579. X    return( exitcode!=0 );
  1580. X}
  1581. X
  1582. X
  1583. X/*
  1584. X * Find out who the sender is.  Try getlogin(), and if that
  1585. X * differs from the REAL uid, make sure both names appear.
  1586. X * Return 1 if we are root, 0 otherwise.
  1587. X */
  1588. Xstatic int
  1589. Xgetsender()
  1590. X{
  1591. X    extern char *getlogin(), *getenv();
  1592. X    struct passwd *pw;
  1593. X    char pwname[USERIDSPACE];
  1594. X    char *glog;
  1595. X
  1596. X    ruid = uid = getuid();
  1597. X
  1598. X    /* Check out who we're running as */
  1599. X    if ( (pw=getpwuid(uid)) == NULL )
  1600. X    fatal("Your uid number (%d) isn't recognized.\n", uid);
  1601. X    if(pw->pw_name == NULL || pw->pw_name[0] == '\0')
  1602. X    fatal("No pwname is associated with uid %d.\n", uid);
  1603. X#ifdef REALUSER
  1604. X    (void) strcpy( pwname, realuser( pw ) );
  1605. X#else
  1606. X    (void) strcpy( pwname,  pw->pw_name );
  1607. X#endif
  1608. X
  1609. X    /* see if we can use getlogin() to see who it is */
  1610. X    (void) strcpy( loginname, (glog=getlogin()) == 0 ? "" : glog );
  1611. X    if ( *loginname ) {
  1612. X    /* check the passwd file for this guy */
  1613. X    pw = getpwnam( loginname );
  1614. X    if ( pw ) {
  1615. X        ruid = pw->pw_uid;
  1616. X#ifdef DUMBSHORT
  1617. X        {
  1618. X        struct utmp *ut;
  1619. X        if ( strncmp( pwname, loginname, sizeof(ut->ut_name) ) == 0 )
  1620. X            (void) strcpy( loginname, pwname );
  1621. X        }
  1622. X#endif
  1623. X#ifdef REALUSER
  1624. X        (void) strcpy( loginname, realuser( pw ) );
  1625. X#endif
  1626. X    }
  1627. X    } else {
  1628. X    /* no better guess at real identity, use USER if we're root */
  1629. X    if ( uid == SU && (glog=getenv("USER"))!=(char *)NULL && *glog ) {
  1630. X        /* look up the pw entry for USER */
  1631. X        if ( (pw=getpwnam(glog)) != (struct passwd *)NULL ) {
  1632. X        ruid = pw->pw_uid;
  1633. X#ifdef REALUSER
  1634. X        glog = realuser( pw );
  1635. X#endif
  1636. X        }
  1637. X        strcpy( loginname, glog );
  1638. X    } else
  1639. X        strcpy( loginname, pwname );
  1640. X    }
  1641. X
  1642. X    if (
  1643. X#ifdef REALUSER
  1644. X        ! sameuser( pwname, loginname )
  1645. X#else
  1646. X    strcmp( pwname, loginname ) != 0
  1647. X#endif
  1648. X    && uid != SU ) {
  1649. X    /* Names differ, and user isn't SU, so send both */
  1650. X    (void) sprintf(sender, "%s(%s)@%s", loginname, pwname, hostname);
  1651. X    } else {
  1652. X    (void) sprintf(sender, "%s@%s", loginname, hostname);
  1653. X    }
  1654. X
  1655. X    return( uid == SU );
  1656. X}
  1657. X
  1658. X
  1659. Xprivate int
  1660. Xsendmsg( recipient, message, fromroot )
  1661. Xchar *recipient, *message;
  1662. Xint fromroot;
  1663. X{
  1664. X    register char *p, *user, *host;
  1665. X#ifndef REMOTE
  1666. X    int local = FALSE;
  1667. X#endif
  1668. X    int errcode;
  1669. X    if ( (p = index( recipient, '@' )) != CPNULL ) {
  1670. X    user = recipient;
  1671. X    host = p+1;
  1672. X    *p = '\0';
  1673. X    } else if ( (p = index( recipient, '!' )) != CPNULL ) {
  1674. X    user = p+1;
  1675. X    host = recipient;
  1676. X    *p = '\0';
  1677. X    } else {
  1678. X    user = recipient;
  1679. X    host = hostname;
  1680. X    }
  1681. X/* always go via the daemon, because it means we don't have to be
  1682. X  setuid, and it makes things a little bit simpler.  I hope - jms.
  1683. X  wrong - jms */
  1684. X#ifndef REMOTE
  1685. X    /* this only works if they use the full host name, not an alias, but
  1686. X       that's okay ... */
  1687. X    if ( strcmp( host, hostname ) == 0 )
  1688. X    local = TRUE;
  1689. X    if ( local )
  1690. X    errcode = deliver( sender, user, message, fromroot );
  1691. X    else
  1692. X#endif
  1693. X    errcode = remote( sender, user, host, message );
  1694. X    return( errcode );
  1695. X}
  1696. X
  1697. X
  1698. X
  1699. X/* Warn user on tname if he/she can't receive messages.
  1700. X */
  1701. Xprivate void
  1702. Xreplywarn(tname)
  1703. X    char *tname;
  1704. X{
  1705. X    struct utmp ut;
  1706. X    struct stat sbuf;
  1707. X    FILE *fp;
  1708. X    char *p;
  1709. X    char terminal[80];    /* should be enough ... */
  1710. X
  1711. X    if( (fp=fopen( UTMP, "r" )) == FPNULL ) {
  1712. X    errmsg( NO_UTMP, hostname, syserr() );
  1713. X    } else {
  1714. X    if( (p=rindex(tname,'/')) != NULL )
  1715. X        tname = p + 1;
  1716. X    while ( fread((char*)&ut,sizeof(struct utmp),1,fp) != 0 ){
  1717. X        if( strncmp(tname,ut.ut_line,(int)sizeof(ut.ut_line)) == 0 ){
  1718. X        (void) sprintf( terminal, "%s%s", DEV, tname );
  1719. X        if ( stat(terminal,&sbuf)!=-1 && ((sbuf.st_mode&ALLOW)==0) )
  1720. X            errmsg( NO_REPLY, loginname, tname );
  1721. X#ifdef ANSWERBACK
  1722. X        answerback( ANS_WARN, loginname, tname );
  1723. X#endif
  1724. X        break;    /* only need to check the first match */
  1725. X        }
  1726. X    }
  1727. X    (void) fclose( fp );
  1728. X    }
  1729. X}
  1730. X
  1731. X
  1732. Xprivate void
  1733. Xusage()
  1734. X{
  1735. X    errprintf( "Usage: %s [-l] [-m message] [-p] [-r] [-t] [user ...]",
  1736. X    progname );
  1737. X    exit( BAD_ARGS );
  1738. X}
  1739. X
  1740. X
  1741. X#ifdef VARARGS
  1742. Xerrprintf( s, va_alist )
  1743. Xchar *s;
  1744. Xva_dcl
  1745. X{
  1746. X    va_list ap;
  1747. X    (void) fprintf( stderr, "%s: ", progname );
  1748. X    va_start( ap );
  1749. X    (void) vfprintf( stderr, s, ap );
  1750. X    va_end( ap );
  1751. X    (void) fputc( '\n', stderr );
  1752. X}
  1753. X
  1754. Xvoid
  1755. Xfatal( s, va_alist )
  1756. Xchar *s;
  1757. Xva_dcl
  1758. X{
  1759. X    va_list ap;
  1760. X    (void) fprintf( stderr, "%s: ", progname );
  1761. X    va_start( ap );
  1762. X    (void) vfprintf( stderr, s, ap );
  1763. X    va_end( ap );
  1764. X    (void) fputc( '\n', stderr );
  1765. X    exit( FATAL );
  1766. X}
  1767. X
  1768. X/* VARARGS1 */
  1769. Xerrmsg( msgnum, va_alist )
  1770. Xint msgnum;
  1771. Xva_dcl
  1772. X{
  1773. X    va_list ap;
  1774. X    (void) fprintf( stderr, "%s: ", progname );
  1775. X    va_start( ap );
  1776. X    (void) vfprintf( stderr, errmessages[msgnum], ap );
  1777. X    va_end( ap );
  1778. X    (void) fputc( '\n', stderr );
  1779. X}
  1780. X#else
  1781. X/* VARARGS1 */
  1782. Xerrprintf( a, b, c, d, e, f, g, h, i, j, k )
  1783. Xchar *a;
  1784. X{
  1785. X    (void) fprintf( stderr, "%s: ", progname );
  1786. X    fprintf( stderr, a, b, c, d, e, f, g, h, i, j, k );
  1787. X    (void) fputc( '\n', stderr );
  1788. X}
  1789. X
  1790. X/* VARARGS1 */
  1791. Xvoid
  1792. Xfatal( a, b, c, d, e, f, g, h, i, j, k )
  1793. Xchar *a;
  1794. X{
  1795. X    (void) fprintf( stderr, "%s: ", progname );
  1796. X    fprintf( stderr, a, b, c, d, e, f, g, h, i, j, k );
  1797. X    (void) fputc( '\n', stderr );
  1798. X    exit( FATAL );
  1799. X}
  1800. X
  1801. X/* VARARGS1 */
  1802. Xerrmsg( msgnum, a, b, c, d, e )
  1803. Xint msgnum;
  1804. Xchar *a, *b, *c, *d, *e;
  1805. X{
  1806. X    errprintf( errmessages[msgnum], a, b, c, d, e );
  1807. X}
  1808. X#endif /* VARARGS */
  1809. X
  1810. Xlist_msgtime()
  1811. X{
  1812. X    /*
  1813. X     * List time last msg was received.
  1814. X     */
  1815. X    struct stat statbuf;
  1816. X
  1817. X    if (stat(msg_file, &statbuf) == -1)
  1818. X    errprintf("can't get date of message file '%s': %s",
  1819. X        msg_file, syserr());
  1820. X    else
  1821. X    printf("last message received %s", ctime(&statbuf.st_mtime));
  1822. X}
  1823. X
  1824. X
  1825. Xlist_msg()
  1826. X{
  1827. X    /*
  1828. X     * List message to which we are replying.
  1829. X     * Just cat the last msg file.
  1830. X     */
  1831. X
  1832. X    FILE *fp;
  1833. X    int c;
  1834. X        
  1835. X    if ( (fp = fopen(msg_file, "r")) == NULL ) {
  1836. X    errprintf("Cannot read last message file '%s'", msg_file );
  1837. X    } else {
  1838. X    while ( (c = getc(fp)) != EOF ) {
  1839. X        putchar(c);
  1840. X    }
  1841. X    }
  1842. X}
  1843. X
  1844. X
  1845. Xprivate void
  1846. Xgetprevious( buf, size )
  1847. Xchar *buf;
  1848. Xint size;
  1849. X{
  1850. X    struct stat sbuf;
  1851. X    FILE *pfp;
  1852. X    int count;
  1853. X    if ( stat( pmsg_file, &sbuf ) == -1 )
  1854. X    fatal( "Could not stat previous message file '%s': %s",
  1855. X        pmsg_file, syserr() );
  1856. X    if ( sbuf.st_uid != ruid )
  1857. X    fatal( "You do not own previous message file '%s'", pmsg_file );
  1858. X    if ( (pfp = fopen( pmsg_file, "r" )) == (FILE *)NULL )
  1859. X    fatal( "Could not fopen previous message file '%s' for read: %s",
  1860. X        pmsg_file, syserr() );
  1861. X    if ( fgets( buf, size, pfp ) == NULL )
  1862. X    fatal( "Could not read previous message from file '%s' (empty?)",
  1863. X        pmsg_file );
  1864. X    /* In case the file didn't end with a \n, we want to make sure that
  1865. X       we don't complain above that it has been truncated.  This is kind
  1866. X       of gross. */
  1867. X    if ( strlen( buf ) < size )
  1868. X    strcat( buf, "\n" );
  1869. X    (void) fclose( pfp );
  1870. X}
  1871. X
  1872. Xprivate void
  1873. Xputprevious( msg )
  1874. Xchar *msg;
  1875. X{
  1876. X    FILE *pfp;
  1877. X    if ( (pfp = fopen( pmsg_file, "w" )) == (FILE *)NULL ) {
  1878. X    errprintf( "Could not fopen previous message file '%s' for write: %s",
  1879. X        pmsg_file, syserr() );
  1880. X    } else {
  1881. X    fprintf( pfp, "%s\n", msg );
  1882. X    fclose( pfp );
  1883. X    chown( pmsg_file, ruid, -1 );
  1884. X    chmod( pmsg_file, 0600 );
  1885. X    }
  1886. X}
  1887. X
  1888. X
  1889. X
  1890. X
  1891. X/*
  1892. X * reply_to - look in MSGFILE to see who sent us
  1893. X *  the last message.
  1894. X */
  1895. X
  1896. Xchar *
  1897. Xreply_to()
  1898. X{
  1899. X    register char *p;
  1900. X    char *index();
  1901. X    static char buf[80];    /* Static 'cause we return what's in it. */
  1902. X    char userfrom[40], whocares[40], hostfrom[40];
  1903. X    FILE *f;
  1904. X
  1905. X    if ( (f = fopen(msg_file, "r")) == NULL ) {
  1906. X    return( NULL );
  1907. X    }
  1908. X
  1909. X    if ( fgets(buf, sizeof(buf),f) == NULL )
  1910. X    return( NULL );
  1911. X    /*
  1912. X     * The file can look like
  1913. X     * user@host: msg
  1914. X     * or
  1915. X     * user(somebody)@host: msg
  1916. X     * Scan this in a basically cheap way.
  1917. X     * I suppose some goofball exceptions could slip through
  1918. X     * here if people had () in their login or host name, blah.
  1919. X     */
  1920. X    
  1921. X
  1922. X    if ( (p = index(buf, ':')) == NULL ) {
  1923. X    return( NULL );    /* Bad format. */
  1924. X    }
  1925. X    *p = '\0';
  1926. X
  1927. X    /*
  1928. X     * Now see which format we have.  Strip out intermediate name.
  1929. X     * there are probably more rigorous ways to do this
  1930. X     */
  1931. X    p = index(buf, '(');
  1932. X
  1933. X    if ( p != NULL ) {
  1934. X    *p++ = '\0';        /* First part is username */
  1935. X    p = index(p, ')');    /* Skip middle bit. */
  1936. X    if ( p == NULL ) {
  1937. X        return(NULL);    /* Bad format */
  1938. X    }
  1939. X
  1940. X    if ( *++p != '@' )
  1941. X        return(NULL);
  1942. X
  1943. X    strcat(buf, p);        /* Tack on hostname. */
  1944. X    }
  1945. X
  1946. X    return( buf );
  1947. X}
  1948. END_OF_FILE
  1949. if test 12537 -ne `wc -c <'./msg/msg.c'`; then
  1950.     echo shar: \"'./msg/msg.c'\" unpacked with wrong size!
  1951. fi
  1952. # end of './msg/msg.c'
  1953. fi
  1954. if test -f './msg/remote.c' -a "${1}" != "-c" ; then 
  1955.   echo shar: Will not clobber existing file \"'./msg/remote.c'\"
  1956. else
  1957. echo shar: Extracting \"'./msg/remote.c'\" \(4372 characters\)
  1958. sed "s/^X//" >'./msg/remote.c' <<'END_OF_FILE'
  1959. X#ifndef lint
  1960. Xstatic char *RCSid = "$Header: /source/users/msg/msg/RCS/remote.c,v 1.5 91/08/13 23:59:09 jmsellens Exp $";
  1961. X#endif
  1962. X
  1963. X/* remote.c
  1964. X   Deliver a message to a user on a remote machine using TCP/IP.
  1965. X*/
  1966. X
  1967. X#include "msg.h"
  1968. X#include <sys/types.h>
  1969. X#include <sys/socket.h>
  1970. X#include <netinet/in.h>
  1971. X#include <netdb.h>
  1972. X#include <arpa/inet.h>
  1973. X
  1974. Xchar *syserr();
  1975. X
  1976. Xprivate    int            sock = -1;    /* the socket */
  1977. Xprivate    struct sockaddr_in    sin;
  1978. X
  1979. X
  1980. Xprivate struct hostent *
  1981. Xfind_host( desthost )
  1982. Xchar *desthost;
  1983. X{
  1984. X    /* stolen from finger */
  1985. X    static struct hostent def;
  1986. X    static struct in_addr defaddr;
  1987. X    static char *alist[1];
  1988. X    static char namebuf[128];
  1989. X    struct hostent *hp;
  1990. X
  1991. X    hp = gethostbyname(desthost);
  1992. X    if (hp == NULL) {
  1993. X    defaddr.s_addr = inet_addr(desthost);
  1994. X    if (defaddr.s_addr == -1)
  1995. X        return( (struct hostent *)NULL );
  1996. X    strcpy(namebuf, desthost);
  1997. X    def.h_name = namebuf;
  1998. X#ifdef h_addr
  1999. X    /* older things don't have this field.  Newer ones #define h_addr */
  2000. X    def.h_addr_list = alist;
  2001. X#endif
  2002. X    def.h_addr = (char *)&defaddr;
  2003. X    def.h_length = sizeof (struct in_addr);
  2004. X    def.h_addrtype = AF_INET;
  2005. X    def.h_aliases = 0;
  2006. X    hp = &def;
  2007. X    }
  2008. X    return( hp );
  2009. X}
  2010. X
  2011. X
  2012. Xprivate int
  2013. Xstart_remote( desthost )
  2014. Xchar *desthost;
  2015. X{
  2016. X    static struct servent *sp = NULL;
  2017. X    struct hostent *hp;
  2018. X    char buf[BUFSIZ];
  2019. X    version ver;
  2020. X    int errcode, i;
  2021. X
  2022. X    if (sp == NULL)
  2023. X        sp = getservbyname( "msg", "tcp" );
  2024. X    if (sp == NULL)
  2025. X    fatal( "msg/tcp not defined in services file" );
  2026. X    hp = find_host( desthost );
  2027. X    if (hp == NULL) {
  2028. X    errmsg( BAD_HOST, desthost );
  2029. X    return( BAD_HOST );
  2030. X    }
  2031. X    bzero( (char *)&sin, sizeof(sin) );
  2032. X    bcopy( hp->h_addr, (char *)&sin.sin_addr, hp->h_length );
  2033. X    sin.sin_family    = hp->h_addrtype;
  2034. X    sin.sin_port    = sp->s_port;
  2035. X    sock = socket( hp->h_addrtype, SOCK_STREAM, 0 );
  2036. X    if (sock < 0)
  2037. X    fatal( "couldn't create socket: %s", syserr() );
  2038. X    if (connect( sock, (char *)&sin, sizeof(sin) ) < 0) {
  2039. X    errmsg( NO_CONNECT, desthost, syserr() );
  2040. X    (void) close(sock);
  2041. X    sock = -1;
  2042. X    return( NO_CONNECT );
  2043. X    }
  2044. X    /* Now make sure we have a compatible version */
  2045. X    ver.v.zero = htonl(0);
  2046. X    ver.v.vnum = htonl(VERSION);
  2047. X    if ( write( sock, &ver, sizeof(ver) ) < 0 )
  2048. X    return( REMOTE_WRITE );
  2049. X    errcode = readint( &i );
  2050. X    if ( errcode == OK )
  2051. X    errcode = i;
  2052. X    if ( errcode == VERSION_OK ) {
  2053. X    errcode = OK;
  2054. X    } else if ( errcode == ERROR_MESSAGE ) {
  2055. X    int code = readint( &i );
  2056. X    if ( code == OK ) {
  2057. X        code = read( sock, buf, i );
  2058. X        if ( code == -1 ) {
  2059. X        errcode = REMOTE_READ;
  2060. X        } else {
  2061. X        buf[i] = '\0';
  2062. X        errprintf( buf );
  2063. X        }
  2064. X    } else
  2065. X        errcode = code;
  2066. X    }
  2067. X    return( errcode );
  2068. X}
  2069. X
  2070. X
  2071. Xprivate
  2072. Xstop_remote()
  2073. X{
  2074. X    if ( sock >= 0 ) {
  2075. X    (void) close( sock );
  2076. X    sock = -1;
  2077. X    }
  2078. X}
  2079. X
  2080. X
  2081. Xint
  2082. Xremote( sender, user, desthost, message )
  2083. Xchar *sender, *user, *desthost, *message;
  2084. X{
  2085. X    char buf[BUFSIZ];
  2086. X    int errcode;
  2087. X    if ( (errcode = start_remote( desthost )) == OK ) {
  2088. X    int writeerr = 0;
  2089. X    header h;
  2090. X    h.slen = htonl(strlen(sender));
  2091. X    h.ulen = htonl(strlen(user));
  2092. X    h.mlen = htonl(strlen(message));
  2093. X    if ( write( sock, (char *)&h, sizeof(h) ) < 0 ) writeerr++;
  2094. X    if ( write( sock, sender, strlen(sender) ) < 0 ) writeerr++;
  2095. X    if ( write( sock, user, strlen(user) ) < 0 ) writeerr++;
  2096. X    if ( write( sock, message, strlen(message) ) < 0 ) writeerr++;
  2097. X    if ( writeerr ) {
  2098. X        errcode = REMOTE_WRITE;
  2099. X    } else {
  2100. X        do {
  2101. X        int i;
  2102. X        errcode = readint( &i );
  2103. X        if ( errcode == OK ) errcode = i;
  2104. X        if ( errcode == ERROR_MESSAGE ) {
  2105. X            int code = readint( &i );
  2106. X            if ( code == OK ) {
  2107. X            code = read( sock, buf, i );
  2108. X            if ( code == -1 ) {
  2109. X                errcode = REMOTE_READ;
  2110. X            } else {
  2111. X                buf[i] = '\0';
  2112. X                errprintf( buf );
  2113. X            }
  2114. X            } else
  2115. X            errcode = code;
  2116. X        }
  2117. X        } while ( errcode == ERROR_MESSAGE );
  2118. X    }
  2119. X    }
  2120. X    switch ( errcode ) {
  2121. X    case REMOTE_READ:
  2122. X    case REMOTE_WRITE:
  2123. X        errmsg( errcode, desthost, syserr() );
  2124. X        break;
  2125. X    case NO_ACK:
  2126. X        errmsg( errcode, desthost );
  2127. X        break;
  2128. X    default:    /* do nothing - got message back from remote */
  2129. X        break;
  2130. X    }
  2131. X    stop_remote(); /* hope close doesn't change errno */
  2132. X    return( errcode );
  2133. X}
  2134. X
  2135. X
  2136. Xint
  2137. Xreadint(np)
  2138. Xint *np;
  2139. X{
  2140. X    int n;
  2141. X
  2142. X    switch (read(sock, &n, sizeof n)) {
  2143. X    case 0:
  2144. X        return( NO_ACK );
  2145. X    case sizeof(n):
  2146. X        *np = ntohl(n);
  2147. X        return( OK );
  2148. X    case -1:
  2149. X    default:    /* for incomplete data */
  2150. X        return( REMOTE_READ );
  2151. X    }
  2152. X    /* NOTREACHED */
  2153. X}
  2154. END_OF_FILE
  2155. if test 4372 -ne `wc -c <'./msg/remote.c'`; then
  2156.     echo shar: \"'./msg/remote.c'\" unpacked with wrong size!
  2157. fi
  2158. # end of './msg/remote.c'
  2159. fi
  2160. if test ! -d './msgd' ; then
  2161.     echo shar: Creating directory \"'./msgd'\"
  2162.     mkdir './msgd'
  2163. fi
  2164. if test -f './msgd/Makefile' -a "${1}" != "-c" ; then 
  2165.   echo shar: Will not clobber existing file \"'./msgd/Makefile'\"
  2166. else
  2167. echo shar: Extracting \"'./msgd/Makefile'\" \(755 characters\)
  2168. sed "s/^X//" >'./msgd/Makefile' <<'END_OF_FILE'
  2169. XNAME    = msgd
  2170. XSERVDIR    = /software/users/servers
  2171. XMANDIR    = /software/users/man
  2172. XMODE    = 555
  2173. X
  2174. XCFLAGS= -DINETD -I../Include
  2175. X
  2176. XOBJECT    = msgd.o server.o deliver.o misc.o savemsg.o errtext.o answerback.o
  2177. X
  2178. Xall: $(NAME)
  2179. X
  2180. X$(NAME): $(OBJECT)
  2181. X    cc -o $(NAME) $(OBJECT)
  2182. X
  2183. Xinstall: $(NAME)
  2184. X    install -s -m $(MODE) $(NAME) $(SERVDIR)/$(NAME)
  2185. X
  2186. Xclean:
  2187. X    rm -f a.out core *.o $(NAME)
  2188. X
  2189. X$(OBJECT): ../Include/msg.h ../Include/msgoptions.h
  2190. X
  2191. Xanswerback.o: ../Common/answerback.c
  2192. X    cc $(CFLAGS) -c ../Common/answerback.c
  2193. X
  2194. Xdeliver.o: ../Common/deliver.c
  2195. X    cc $(CFLAGS) -c ../Common/deliver.c
  2196. X
  2197. Xerrtext.o: ../Common/errtext.c
  2198. X    cc $(CFLAGS) -c ../Common/errtext.c
  2199. X
  2200. Xmisc.o: ../Common/misc.c
  2201. X    cc $(CFLAGS) -c ../Common/misc.c
  2202. X
  2203. Xsavemsg.o: ../Common/savemsg.c
  2204. X    cc $(CFLAGS) -c ../Common/savemsg.c
  2205. END_OF_FILE
  2206. if test 755 -ne `wc -c <'./msgd/Makefile'`; then
  2207.     echo shar: \"'./msgd/Makefile'\" unpacked with wrong size!
  2208. fi
  2209. # end of './msgd/Makefile'
  2210. fi
  2211. if test -f './msgd/msgd.c' -a "${1}" != "-c" ; then 
  2212.   echo shar: Will not clobber existing file \"'./msgd/msgd.c'\"
  2213. else
  2214. echo shar: Extracting \"'./msgd/msgd.c'\" \(3944 characters\)
  2215. sed "s/^X//" >'./msgd/msgd.c' <<'END_OF_FILE'
  2216. X#ifndef lint
  2217. Xstatic char *RCSid = "$Header: /source/users/msg/msgd/RCS/msgd.c,v 1.3 91/08/14 00:00:14 jmsellens Exp $";
  2218. X#endif
  2219. X
  2220. X#if 0
  2221. X/*
  2222. X * $Log:    msgd.c,v $
  2223. X * Revision 1.3  91/08/14  00:00:14  jmsellens
  2224. X * s/eprintf/errprintf/ to avoid libuw clash
  2225. X * 
  2226. X * Revision 1.2  90/12/29  22:03:50  jmsellen
  2227. X * VARARGS and logging changes
  2228. X * 
  2229. X * Revision 1.1  87/08/06  19:06:38  sahayman
  2230. X * Initial revision
  2231. X * 
  2232. X */
  2233. X#endif
  2234. X
  2235. X/* msgd.c
  2236. X   msg daemon
  2237. X   John Sellens, University of Waterloo
  2238. X*/
  2239. X
  2240. X#include "msg.h"
  2241. X#include <signal.h>
  2242. X
  2243. Xchar *syserr();
  2244. Xextern int errno;
  2245. X
  2246. Xchar *progname;
  2247. Xchar hostname[BUFSIZ];
  2248. Xint client;
  2249. X
  2250. Xmain( argc, argv )
  2251. Xint argc;
  2252. Xchar *argv[];
  2253. X{
  2254. X    
  2255. X    progname = argv[0];
  2256. X    if ( gethostname( hostname, sizeof(hostname) ) )
  2257. X    fatal( "Couldn't gethostname(): %s", syserr() );
  2258. X    (void) signal( SIGHUP, SIG_IGN );
  2259. X    (void) signal( SIGINT, SIG_IGN );
  2260. X    (void) signal( SIGALRM, SIG_IGN );
  2261. X    (void) signal( SIGTTIN, SIG_IGN );
  2262. X    (void) signal( SIGTTOU, SIG_IGN );
  2263. X#ifdef INETD
  2264. X     /* Inetd provides the client connection on fd 0. */
  2265. X    client = 0;
  2266. X    server();
  2267. X    exit(0);
  2268. X#else
  2269. X{
  2270. X#include <sys/types.h>
  2271. X#include <sys/socket.h>
  2272. X#include <netinet/in.h>
  2273. X#include <netdb.h>
  2274. X#include <arpa/inet.h>
  2275. X#include <errno.h>
  2276. X#include <sys/ioctl.h>
  2277. X
  2278. X    struct servent *serv;
  2279. X    struct sockaddr_in    sin;
  2280. X    int i, sock;
  2281. X    
  2282. X    if ( argc != 1 )
  2283. X    errprintf( "all arguments ignored" );
  2284. X    serv = getservbyname( "msg", "tcp" );
  2285. X    if ( serv == (struct servent *)0 )
  2286. X    fatal( "msg/tcp not defined in services file" );
  2287. X
  2288. X#ifndef DEBUG
  2289. X    /* disconnect from tty */
  2290. X    switch ( fork() ) {
  2291. X    case 0:    /* child */
  2292. X        break;
  2293. X    case -1:
  2294. X        fatal( "couldn't fork (%s), message daemon not started", syserr() );
  2295. X        break;
  2296. X    default:    /* parent */
  2297. X        exit( 0 );
  2298. X    }
  2299. X    for (i = 0; i < 10; i++)
  2300. X    close(i);
  2301. X    (void) open("/", 0);
  2302. X    dup2(0, 1);
  2303. X    dup2(0, 2);
  2304. X    i = open("/dev/tty", 2);
  2305. X    if (i >= 0) {
  2306. X    ioctl(i, TIOCNOTTY, (char *)0);
  2307. X        close(i);
  2308. X    }
  2309. X#endif
  2310. X
  2311. X    sin.sin_port = serv->s_port;
  2312. X    sock = socket( AF_INET, SOCK_STREAM, 0 );
  2313. X    if ( sock == -1 )
  2314. X    fatal( "couldn't create socket: %s", syserr() );
  2315. X    if ( bind( sock, (caddr_t)&sin, sizeof(sin) ) == -1 )
  2316. X    fatal( "couldn't bind socket: %s", syserr() );
  2317. X    if ( listen( sock, 5 ) == -1 )
  2318. X    fatal( "couldn't listen to socket: %s", syserr() );
  2319. X    
  2320. X    for ( ;; ) {
  2321. X    client = accept(sock, (struct sockaddr *)0, (int *)0);
  2322. X    if ( client < 0 ) {
  2323. X        if ( errno != EINTR ) {
  2324. X        errprintf( "accept: %s", syserr() );
  2325. X        sleep(5);
  2326. X        }
  2327. X        continue;
  2328. X    }
  2329. X    server();
  2330. X    (void) close( client );
  2331. X    }
  2332. X    /* NOTREACHED */
  2333. X    }
  2334. X#endif /* INETD */
  2335. X}
  2336. X
  2337. X#include <syslog.h>
  2338. X
  2339. Xstatic int loglevel = LOG_WARNING;
  2340. X
  2341. Xstatic
  2342. X#ifdef VARARGS
  2343. Xdoerror( s, ap )
  2344. Xchar *s;
  2345. Xva_list ap;
  2346. X#else
  2347. Xdoerror( a, b, c, d, e, f, g, h, i, j, k )
  2348. Xchar *a;
  2349. X#endif
  2350. X{
  2351. X#ifdef DEBUG
  2352. X#ifdef VARARGS
  2353. X    vfprintf(stderr, s, ap);
  2354. X#else
  2355. X    fprintf(stderr, a, b, c, d, e, f, g, h, i, j, k);
  2356. X#endif
  2357. X    putc('\n', stderr);        /* syslog will add this */
  2358. X#else
  2359. X    static int first = 1;
  2360. X
  2361. X    if (first) {
  2362. X#ifdef LOG_DAEMON
  2363. X        openlog(progname, LOG_PID, LOG_DAEMON);
  2364. X#else
  2365. X        openlog(progname, LOG_PID);
  2366. X#endif
  2367. X        first = 0;
  2368. X    }
  2369. X#ifdef VARARGS
  2370. X    {
  2371. X    char buf[BUFSIZ];
  2372. X    vsprintf( buf, s, ap );
  2373. X    syslog( loglevel, buf );
  2374. X    }
  2375. X#else
  2376. X    syslog(loglevel, a, b, c, d, e, f, g, h, i, j, k);
  2377. X#endif
  2378. X#endif
  2379. X}
  2380. X
  2381. X/*VARARGS1*/
  2382. X#ifdef VARARGS
  2383. Xerrprintf( s, va_alist )
  2384. Xchar *s;
  2385. Xva_dcl
  2386. X{
  2387. X    va_list ap;
  2388. X    va_start( ap );
  2389. X    doerror( s, ap );
  2390. X    va_end( ap );
  2391. X}
  2392. X#else
  2393. Xerrprintf( a, b, c, d, e, f, g, h, i, j, k )
  2394. Xchar *a;
  2395. X{
  2396. X    doerror(a, b, c, d, e, f, g, h, i, j, k);
  2397. X}
  2398. X#endif
  2399. X
  2400. X/*VARARGS1*/
  2401. X#ifdef VARARGS
  2402. Xfatal( s, va_alist )
  2403. Xchar *s;
  2404. Xva_dcl
  2405. X{
  2406. X    va_list ap;
  2407. X    loglevel = LOG_ERR;
  2408. X    va_start( ap );
  2409. X    doerror( s, ap );
  2410. X    va_end( ap );
  2411. X    exit( FATAL );
  2412. X}
  2413. X#else
  2414. Xfatal( a, b, c, d, e, f, g, h, i, j, k )
  2415. Xchar *a;
  2416. X{
  2417. X    loglevel = LOG_ERR;
  2418. X    doerror( a, b, c, d, e, f, g, h, i, j, k );
  2419. X    exit( FATAL );
  2420. X}
  2421. X#endif
  2422. END_OF_FILE
  2423. if test 3944 -ne `wc -c <'./msgd/msgd.c'`; then
  2424.     echo shar: \"'./msgd/msgd.c'\" unpacked with wrong size!
  2425. fi
  2426. # end of './msgd/msgd.c'
  2427. fi
  2428. if test -f './msgd/server.c' -a "${1}" != "-c" ; then 
  2429.   echo shar: Will not clobber existing file \"'./msgd/server.c'\"
  2430. else
  2431. echo shar: Extracting \"'./msgd/server.c'\" \(4063 characters\)
  2432. sed "s/^X//" >'./msgd/server.c' <<'END_OF_FILE'
  2433. X#ifndef lint
  2434. Xstatic char *RCSid = "$Header: /source/users/msg/msgd/RCS/server.c,v 1.5 91/08/14 00:00:19 jmsellens Exp $";
  2435. X#endif
  2436. X
  2437. X#if 0
  2438. X/*
  2439. X * $Log:    server.c,v $
  2440. X * Revision 1.5  91/08/14  00:00:19  jmsellens
  2441. X * s/eprintf/errprintf/ to avoid libuw clash
  2442. X * 
  2443. X * Revision 1.4  90/12/29  22:04:11  jmsellen
  2444. X * VARARGS changes
  2445. X * 
  2446. X * Revision 1.3  88/11/07  11:09:54  jmsellens
  2447. X * Call new sanitize() routine to avoid control characters.  This is
  2448. X * necessary to avoid someone modifying the msg source and making
  2449. X * their own nasty client that doesn't behave nicely.
  2450. X * 
  2451. X * Revision 1.2  88/09/25  02:41:31  jmsellens
  2452. X * Added stuff to accept version records in the future.  Taught to
  2453. X * look up the sender's machine name, so that we get the name that
  2454. X * we use to get there, not the value of `hostname` on the remote
  2455. X * machine, which probably isn't properly domain-ized if it's
  2456. X * remote from us.
  2457. X * 
  2458. X * Revision 1.1  87/08/06  19:06:43  sahayman
  2459. X * Initial revision
  2460. X * 
  2461. X */
  2462. X#endif
  2463. X
  2464. X/* server.c
  2465. X   read message coming from server, call deliver, and acknowledge with
  2466. X   result code
  2467. X*/
  2468. X
  2469. X/* We ignore any errors communicating with the client, since we figure
  2470. X   they just dies or broke out or something */
  2471. X
  2472. X#include "msg.h"
  2473. X#include <netinet/in.h>
  2474. X#include <arpa/inet.h>
  2475. X#include <netdb.h>
  2476. X#include <strings.h>
  2477. X
  2478. Xextern int client;
  2479. Xprivate int remote_ver = 0;
  2480. X
  2481. Xserver()
  2482. X{
  2483. X    version ver;
  2484. X    header h;
  2485. X    int err;
  2486. X    char sender[BUFSIZ], user[BUFSIZ], rawmsg[BUFSIZ], message[BUFSIZ];
  2487. X    
  2488. X    if ( read( client, &ver, sizeof(ver) ) != sizeof(ver) ) goto done;
  2489. X    if ( ntohl(ver.v.zero) == 0 ) {
  2490. X    /* got a version struct */
  2491. X    remote_ver = ntohl(ver.v.vnum);
  2492. X    if ( remote_ver > VERSION ) {
  2493. X        errmsg( BAD_VERSION, remote_ver, VERSION );
  2494. X        goto done;
  2495. X    }
  2496. X    /* acknowledge that we agree on the version */
  2497. X    err = htonl(VERSION_OK);
  2498. X    (void) write( client, &err, sizeof(err) );
  2499. X    if ( read( client, &h, sizeof(h) ) != sizeof(h) ) goto done;
  2500. X    } else {
  2501. X    /* Not a version struct, so copy it into header struct */
  2502. X    h = ver.h;
  2503. X    }
  2504. X    h.slen = ntohl(h.slen);
  2505. X    h.ulen = ntohl(h.ulen);
  2506. X    h.mlen = ntohl(h.mlen);
  2507. X    if ( read( client, sender, h.slen ) != h.slen ) goto done;
  2508. X    sender[h.slen] = '\0';
  2509. X    if ( read( client, user, h.ulen ) != h.ulen ) goto done;
  2510. X    user[h.ulen] = '\0';
  2511. X    if ( read( client, rawmsg, h.mlen ) != h.mlen ) goto done;
  2512. X    rawmsg[h.mlen] = '\0';
  2513. X    get_real_sender(sender);
  2514. X    sanitize( rawmsg, message );
  2515. X    err = deliver( sender, user, message, FALSE );
  2516. X    /* deliver gave us a pgrp when it opened a tty... */
  2517. X    setpgrp(0, 0);
  2518. X    err = htonl(err);
  2519. X    (void) write( client, &err, sizeof(err) );
  2520. Xdone:
  2521. X    ;
  2522. X}
  2523. X
  2524. X
  2525. X#ifdef VARARGS
  2526. Xerrmsg( msgnum, va_alist )
  2527. Xint msgnum;
  2528. Xva_dcl
  2529. X#else
  2530. Xerrmsg( msgnum, a, b, c, d, e )
  2531. Xint msgnum;
  2532. Xchar *a, *b, *c, *d, *e;
  2533. X#endif
  2534. X{
  2535. X    char buf[BUFSIZ];
  2536. X    int i = htonl(ERROR_MESSAGE);
  2537. X    
  2538. X    (void) write( client, &i, sizeof(i) );
  2539. X#ifdef VARARGS
  2540. X    {
  2541. X    va_list ap;
  2542. X    va_start( ap );
  2543. X    (void) vsprintf( buf, errmessages[msgnum], ap );
  2544. X    va_end( ap );
  2545. X    }
  2546. X#else
  2547. X    (void) sprintf( buf, errmessages[msgnum], a, b, c, d, e );
  2548. X#endif
  2549. X    i = htonl(strlen( buf ));
  2550. X    (void) write( client, &i, sizeof(i) );
  2551. X    (void) write( client, buf, strlen(buf) );
  2552. X}
  2553. X
  2554. X
  2555. X
  2556. X
  2557. Xget_real_sender( sender )
  2558. Xchar *sender;
  2559. X{
  2560. X    struct sockaddr_in from;
  2561. X    struct hostent *hp;
  2562. X    char *p;
  2563. X    int fromlen;
  2564. X    fromlen = sizeof(from);
  2565. X
  2566. X    p = index( sender, '@' );
  2567. X    if ( p == CPNULL ) {
  2568. X    errprintf( "sender '%s' contains no '@'", sender );
  2569. X    (void) strcat( sender, "@" );
  2570. X    p = index( sender, '@' );
  2571. X    }
  2572. X    p++;
  2573. X    if ( index( p, '@' ) != CPNULL ) {
  2574. X    errprintf( "sender '%s' contains multiple '@'s", sender );
  2575. X    p = rindex( sender, '@' );
  2576. X    p++;
  2577. X    }
  2578. X    if ( getpeername( client, &from, &fromlen ) < 0 ) {
  2579. X    errprintf( "couldn't getpeername(): %s", syserr() );
  2580. X    (void) strcat( sender, "<unknown>" );
  2581. X    } else {
  2582. X    hp = gethostbyaddr( (char *)&from.sin_addr, sizeof(struct in_addr),
  2583. X        from.sin_family );
  2584. X    if ( hp )
  2585. X        (void) strcpy( p, hp->h_name );
  2586. X    else
  2587. X        (void) strcpy( p, inet_ntoa( from.sin_addr ) );
  2588. X    }
  2589. X}
  2590. END_OF_FILE
  2591. if test 4063 -ne `wc -c <'./msgd/server.c'`; then
  2592.     echo shar: \"'./msgd/server.c'\" unpacked with wrong size!
  2593. fi
  2594. # end of './msgd/server.c'
  2595. fi
  2596. if test -f './services' -a "${1}" != "-c" ; then 
  2597.   echo shar: Will not clobber existing file \"'./services'\"
  2598. else
  2599. echo shar: Extracting \"'./services'\" \(40 characters\)
  2600. sed "s/^X//" >'./services' <<'END_OF_FILE'
  2601. Xmsg        1241/tcp            # msgd(8) (under inetd)
  2602. END_OF_FILE
  2603. if test 40 -ne `wc -c <'./services'`; then
  2604.     echo shar: \"'./services'\" unpacked with wrong size!
  2605. fi
  2606. # end of './services'
  2607. fi
  2608. echo shar: End of shell archive.
  2609. exit 0
  2610.